Skip to content

Commit 258b3ac

Browse files
chore: fix caching issue for conditional merchant creation (#68)
1 parent 8a7bbc3 commit 258b3ac

File tree

7 files changed

+108
-9
lines changed

7 files changed

+108
-9
lines changed

src/error.rs

+2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ pub enum StorageError {
5959
DecryptionError,
6060
#[error("Error while encrypting the payload")]
6161
EncryptionError,
62+
#[error("Element not found in storage")]
63+
NotFoundError,
6264
}
6365

6466
#[derive(Debug, Copy, Clone, thiserror::Error)]

src/error/container.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::error::Error;
22

33
pub struct ContainerError<E> {
4-
pub(super) error: error_stack::Report<E>,
4+
pub(crate) error: error_stack::Report<E>,
55
}
66

77
impl<T> std::fmt::Debug for ContainerError<T> {

src/error/custom_error.rs

+12
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ pub enum MerchantDBError {
1010
DBFilterError,
1111
#[error("Error while inserting element in the database")]
1212
DBInsertError,
13+
#[error("Element not found in database")]
14+
NotFoundError,
1315
#[error("Unpredictable error occurred")]
1416
UnknownError,
1517
}
@@ -43,3 +45,13 @@ pub enum HashDBError {
4345
#[error("Unpredictable error occurred")]
4446
UnknownError,
4547
}
48+
49+
pub trait NotFoundError {
50+
fn is_not_found(&self) -> bool;
51+
}
52+
53+
impl NotFoundError for super::ContainerError<MerchantDBError> {
54+
fn is_not_found(&self) -> bool {
55+
matches!(self.error.current_context(), MerchantDBError::NotFoundError)
56+
}
57+
}

src/error/transforms.rs

+4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ impl<'a> From<&'a super::StorageError> for super::MerchantDBError {
4040
| super::StorageError::EncryptionError
4141
| super::StorageError::DeleteError => Self::UnknownError,
4242
super::StorageError::InsertError => Self::DBInsertError,
43+
super::StorageError::NotFoundError => Self::NotFoundError,
4344
}
4445
}
4546
}
@@ -57,6 +58,7 @@ impl<'a> From<&'a super::StorageError> for super::LockerDBError {
5758
}
5859
super::StorageError::InsertError => Self::DBInsertError,
5960
super::StorageError::DeleteError => Self::DBDeleteError,
61+
super::StorageError::NotFoundError => Self::DBFilterError,
6062
}
6163
}
6264
}
@@ -73,6 +75,7 @@ impl<'a> From<&'a super::StorageError> for super::HashDBError {
7375
| super::StorageError::EncryptionError
7476
| super::StorageError::DeleteError => Self::UnknownError,
7577
super::StorageError::InsertError => Self::DBInsertError,
78+
super::StorageError::NotFoundError => Self::DBFilterError,
7679
}
7780
}
7881
}
@@ -103,6 +106,7 @@ impl<'a> From<&'a super::MerchantDBError> for super::ApiError {
103106
// occur because of master key failure
104107
super::MerchantDBError::DBError |
105108
super::MerchantDBError::DBFilterError |
109+
super::MerchantDBError::NotFoundError |
106110
super::MerchantDBError::DBInsertError=> Self::MerchantError,
107111
super::MerchantDBError::UnknownError => Self::UnknownError
108112
}

src/storage/caching/hash_table.rs

+39
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,42 @@ where
3838
Ok(output)
3939
}
4040
}
41+
42+
#[async_trait::async_trait]
43+
impl<T> storage::MerchantInterface for super::Caching<T, types::HashTable>
44+
where
45+
T: storage::MerchantInterface + storage::Cacheable<types::HashTable> + Sync,
46+
{
47+
type Algorithm = T::Algorithm;
48+
type Error = T::Error;
49+
50+
async fn find_by_merchant_id(
51+
&self,
52+
merchant_id: &str,
53+
tenant_id: &str,
54+
key: &Self::Algorithm,
55+
) -> Result<types::Merchant, ContainerError<Self::Error>> {
56+
self.inner
57+
.find_by_merchant_id(merchant_id, tenant_id, key)
58+
.await
59+
}
60+
61+
async fn find_or_create_by_merchant_id(
62+
&self,
63+
merchant_id: &str,
64+
tenant_id: &str,
65+
key: &Self::Algorithm,
66+
) -> Result<types::Merchant, ContainerError<Self::Error>> {
67+
self.inner
68+
.find_or_create_by_merchant_id(merchant_id, tenant_id, key)
69+
.await
70+
}
71+
72+
async fn insert_merchant(
73+
&self,
74+
new: types::MerchantNew<'_>,
75+
key: &Self::Algorithm,
76+
) -> Result<types::Merchant, ContainerError<Self::Error>> {
77+
self.inner.insert_merchant(new, key).await
78+
}
79+
}

src/storage/caching/merchant.rs

+44-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
use futures_util::TryFutureExt;
2+
13
use crate::{
2-
error::ContainerError,
4+
crypto::aes::generate_aes256_key,
5+
error::{ContainerError, NotFoundError},
36
storage::{self, types},
47
};
58

@@ -10,6 +13,7 @@ where
1013
+ storage::Cacheable<types::Merchant, Key = (String, String), Value = types::Merchant>
1114
+ Sync
1215
+ Send,
16+
ContainerError<<T as storage::MerchantInterface>::Error>: NotFoundError,
1317
{
1418
type Algorithm = T::Algorithm;
1519
type Error = T::Error;
@@ -46,8 +50,23 @@ where
4650
tenant_id: &str,
4751
key: &Self::Algorithm,
4852
) -> Result<types::Merchant, ContainerError<Self::Error>> {
49-
self.inner
50-
.find_or_create_by_merchant_id(merchant_id, tenant_id, key)
53+
self.find_by_merchant_id(merchant_id, tenant_id, key)
54+
.or_else(|err| async {
55+
match err.is_not_found() {
56+
false => Err(err),
57+
true => {
58+
self.insert_merchant(
59+
types::MerchantNew {
60+
merchant_id,
61+
tenant_id,
62+
enc_key: generate_aes256_key().to_vec().into(),
63+
},
64+
key,
65+
)
66+
.await
67+
}
68+
}
69+
})
5170
.await
5271
}
5372

@@ -64,3 +83,25 @@ where
6483
Ok(output)
6584
}
6685
}
86+
87+
#[async_trait::async_trait]
88+
impl<T> storage::HashInterface for super::Caching<T, types::Merchant>
89+
where
90+
T: storage::HashInterface + storage::Cacheable<types::Merchant> + Sync,
91+
{
92+
type Error = T::Error;
93+
94+
async fn find_by_data_hash(
95+
&self,
96+
data_hash: &[u8],
97+
) -> Result<Option<types::HashTable>, ContainerError<Self::Error>> {
98+
self.inner.find_by_data_hash(data_hash).await
99+
}
100+
101+
async fn insert_hash(
102+
&self,
103+
data_hash: Vec<u8>,
104+
) -> Result<types::HashTable, ContainerError<Self::Error>> {
105+
self.inner.insert_hash(data_hash).await
106+
}
107+
}

src/storage/db.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@ impl MerchantInterface for Storage {
3333
.get_result(&mut conn)
3434
.await;
3535
output
36-
.change_error(error::StorageError::FindError)
37-
.map_err(From::from)
38-
.and_then(|inner| {
39-
Ok(inner.decrypt(key)?)
40-
// .change_context(error::StorageError::DecryptionError)
36+
.map_err(|error| match error {
37+
diesel::result::Error::NotFound => error::StorageError::NotFoundError,
38+
_ => error::StorageError::FindError,
4139
})
40+
.map_err(error::ContainerError::from)
41+
.map_err(From::from)
42+
.and_then(|inner| Ok(inner.decrypt(key)?))
4243
}
4344

4445
async fn find_or_create_by_merchant_id(

0 commit comments

Comments
 (0)