Skip to content

Commit

Permalink
chore: fix caching issue for conditional merchant creation (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
NishantJoshi00 authored Feb 5, 2024
1 parent 8a7bbc3 commit 258b3ac
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 9 deletions.
2 changes: 2 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ pub enum StorageError {
DecryptionError,
#[error("Error while encrypting the payload")]
EncryptionError,
#[error("Element not found in storage")]
NotFoundError,
}

#[derive(Debug, Copy, Clone, thiserror::Error)]
Expand Down
2 changes: 1 addition & 1 deletion src/error/container.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::error::Error;

pub struct ContainerError<E> {
pub(super) error: error_stack::Report<E>,
pub(crate) error: error_stack::Report<E>,
}

impl<T> std::fmt::Debug for ContainerError<T> {
Expand Down
12 changes: 12 additions & 0 deletions src/error/custom_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub enum MerchantDBError {
DBFilterError,
#[error("Error while inserting element in the database")]
DBInsertError,
#[error("Element not found in database")]
NotFoundError,
#[error("Unpredictable error occurred")]
UnknownError,
}
Expand Down Expand Up @@ -43,3 +45,13 @@ pub enum HashDBError {
#[error("Unpredictable error occurred")]
UnknownError,
}

pub trait NotFoundError {
fn is_not_found(&self) -> bool;
}

impl NotFoundError for super::ContainerError<MerchantDBError> {
fn is_not_found(&self) -> bool {
matches!(self.error.current_context(), MerchantDBError::NotFoundError)
}
}
4 changes: 4 additions & 0 deletions src/error/transforms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ impl<'a> From<&'a super::StorageError> for super::MerchantDBError {
| super::StorageError::EncryptionError
| super::StorageError::DeleteError => Self::UnknownError,
super::StorageError::InsertError => Self::DBInsertError,
super::StorageError::NotFoundError => Self::NotFoundError,
}
}
}
Expand All @@ -57,6 +58,7 @@ impl<'a> From<&'a super::StorageError> for super::LockerDBError {
}
super::StorageError::InsertError => Self::DBInsertError,
super::StorageError::DeleteError => Self::DBDeleteError,
super::StorageError::NotFoundError => Self::DBFilterError,
}
}
}
Expand All @@ -73,6 +75,7 @@ impl<'a> From<&'a super::StorageError> for super::HashDBError {
| super::StorageError::EncryptionError
| super::StorageError::DeleteError => Self::UnknownError,
super::StorageError::InsertError => Self::DBInsertError,
super::StorageError::NotFoundError => Self::DBFilterError,
}
}
}
Expand Down Expand Up @@ -103,6 +106,7 @@ impl<'a> From<&'a super::MerchantDBError> for super::ApiError {
// occur because of master key failure
super::MerchantDBError::DBError |
super::MerchantDBError::DBFilterError |
super::MerchantDBError::NotFoundError |
super::MerchantDBError::DBInsertError=> Self::MerchantError,
super::MerchantDBError::UnknownError => Self::UnknownError
}
Expand Down
39 changes: 39 additions & 0 deletions src/storage/caching/hash_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,42 @@ where
Ok(output)
}
}

#[async_trait::async_trait]
impl<T> storage::MerchantInterface for super::Caching<T, types::HashTable>
where
T: storage::MerchantInterface + storage::Cacheable<types::HashTable> + Sync,
{
type Algorithm = T::Algorithm;
type Error = T::Error;

async fn find_by_merchant_id(
&self,
merchant_id: &str,
tenant_id: &str,
key: &Self::Algorithm,
) -> Result<types::Merchant, ContainerError<Self::Error>> {
self.inner
.find_by_merchant_id(merchant_id, tenant_id, key)
.await
}

async fn find_or_create_by_merchant_id(
&self,
merchant_id: &str,
tenant_id: &str,
key: &Self::Algorithm,
) -> Result<types::Merchant, ContainerError<Self::Error>> {
self.inner
.find_or_create_by_merchant_id(merchant_id, tenant_id, key)
.await
}

async fn insert_merchant(
&self,
new: types::MerchantNew<'_>,
key: &Self::Algorithm,
) -> Result<types::Merchant, ContainerError<Self::Error>> {
self.inner.insert_merchant(new, key).await
}
}
47 changes: 44 additions & 3 deletions src/storage/caching/merchant.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use futures_util::TryFutureExt;

use crate::{
error::ContainerError,
crypto::aes::generate_aes256_key,
error::{ContainerError, NotFoundError},
storage::{self, types},
};

Expand All @@ -10,6 +13,7 @@ where
+ storage::Cacheable<types::Merchant, Key = (String, String), Value = types::Merchant>
+ Sync
+ Send,
ContainerError<<T as storage::MerchantInterface>::Error>: NotFoundError,
{
type Algorithm = T::Algorithm;
type Error = T::Error;
Expand Down Expand Up @@ -46,8 +50,23 @@ where
tenant_id: &str,
key: &Self::Algorithm,
) -> Result<types::Merchant, ContainerError<Self::Error>> {
self.inner
.find_or_create_by_merchant_id(merchant_id, tenant_id, key)
self.find_by_merchant_id(merchant_id, tenant_id, key)
.or_else(|err| async {
match err.is_not_found() {
false => Err(err),
true => {
self.insert_merchant(
types::MerchantNew {
merchant_id,
tenant_id,
enc_key: generate_aes256_key().to_vec().into(),
},
key,
)
.await
}
}
})
.await
}

Expand All @@ -64,3 +83,25 @@ where
Ok(output)
}
}

#[async_trait::async_trait]
impl<T> storage::HashInterface for super::Caching<T, types::Merchant>
where
T: storage::HashInterface + storage::Cacheable<types::Merchant> + Sync,
{
type Error = T::Error;

async fn find_by_data_hash(
&self,
data_hash: &[u8],
) -> Result<Option<types::HashTable>, ContainerError<Self::Error>> {
self.inner.find_by_data_hash(data_hash).await
}

async fn insert_hash(
&self,
data_hash: Vec<u8>,
) -> Result<types::HashTable, ContainerError<Self::Error>> {
self.inner.insert_hash(data_hash).await
}
}
11 changes: 6 additions & 5 deletions src/storage/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ impl MerchantInterface for Storage {
.get_result(&mut conn)
.await;
output
.change_error(error::StorageError::FindError)
.map_err(From::from)
.and_then(|inner| {
Ok(inner.decrypt(key)?)
// .change_context(error::StorageError::DecryptionError)
.map_err(|error| match error {
diesel::result::Error::NotFound => error::StorageError::NotFoundError,
_ => error::StorageError::FindError,
})
.map_err(error::ContainerError::from)
.map_err(From::from)
.and_then(|inner| Ok(inner.decrypt(key)?))
}

async fn find_or_create_by_merchant_id(
Expand Down

0 comments on commit 258b3ac

Please sign in to comment.