Skip to content

Commit

Permalink
fix: add fallback to reverselookup error
Browse files Browse the repository at this point in the history
  • Loading branch information
dracarys18 committed Nov 30, 2023
1 parent de8e31b commit ecae9fc
Show file tree
Hide file tree
Showing 13 changed files with 274 additions and 210 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/common_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod errors;
pub mod events;
pub mod ext_traits;
pub mod fp_utils;
pub mod macros;
pub mod pii;
#[allow(missing_docs)] // Todo: add docs
pub mod request;
Expand Down
92 changes: 92 additions & 0 deletions crates/common_utils/src/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#![allow(missing_docs)]

#[macro_export]
macro_rules! newtype_impl {
($is_pub:vis, $name:ident, $ty_path:path) => {
impl std::ops::Deref for $name {
type Target = $ty_path;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl std::ops::DerefMut for $name {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl From<$ty_path> for $name {
fn from(ty: $ty_path) -> Self {
Self(ty)
}
}

impl $name {
pub fn into_inner(self) -> $ty_path {
self.0
}
}
};
}

#[macro_export]
macro_rules! newtype {
($is_pub:vis $name:ident = $ty_path:path) => {
$is_pub struct $name(pub $ty_path);

$crate::newtype_impl!($is_pub, $name, $ty_path);
};

($is_pub:vis $name:ident = $ty_path:path, derives = ($($trt:path),*)) => {
#[derive($($trt),*)]
$is_pub struct $name(pub $ty_path);

$crate::newtype_impl!($is_pub, $name, $ty_path);
};
}

#[macro_export]
macro_rules! async_spawn {
($t:block) => {
tokio::spawn(async move { $t });
};
}

#[macro_export]
macro_rules! if_err_reverse_lookup {
($a:expr,$b:expr) => {
match $a {
Ok(res) => res,
Err(err) => {
router_env::logger::error!(wtf_err = %err);
match err.current_context() {
errors::StorageError::ValueNotFound(_) => return $b,
errors::StorageError::DatabaseError(data_err) => {
match data_err.current_context() {
diesel_models::errors::DatabaseError::NotFound => return $b,
_ => return Err(err)
}
}
_=> return Err(err)
}
}
};
};
}

#[macro_export]
macro_rules! collect_missing_value_keys {
[$(($key:literal, $option:expr)),+] => {
{
let mut keys: Vec<&'static str> = Vec::new();
$(
if $option.is_none() {
keys.push($key);
}
)*
keys
}
};
}
1 change: 1 addition & 0 deletions crates/data_models/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ api_models = { version = "0.1.0", path = "../api_models" }
common_enums = { version = "0.1.0", path = "../common_enums" }
common_utils = { version = "0.1.0", path = "../common_utils" }
masking = { version = "0.1.0", path = "../masking" }
diesel_models = { version = "0.1.0", path = "../diesel_models", features = ["kv_store"] }

# Third party deps
async-trait = "0.1.68"
Expand Down
4 changes: 3 additions & 1 deletion crates/data_models/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use diesel_models::errors::DatabaseError;

pub type StorageResult<T> = error_stack::Result<T, StorageError>;

#[derive(Debug, thiserror::Error)]
Expand All @@ -6,7 +8,7 @@ pub enum StorageError {
InitializationError,
// TODO: deprecate this error type to use a domain error instead
#[error("DatabaseError: {0:?}")]
DatabaseError(String),
DatabaseError(error_stack::Report<DatabaseError>),
#[error("ValueNotFound: {0}")]
ValueNotFound(String),
#[error("DuplicateValue: {entity} already exists {key:?}")]
Expand Down
16 changes: 15 additions & 1 deletion crates/diesel_models/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#[derive(Debug, thiserror::Error)]
#[derive(Copy, Clone, Debug, thiserror::Error)]
pub enum DatabaseError {
#[error("An error occurred when obtaining database connection")]
DatabaseConnectionError,
Expand All @@ -14,3 +14,17 @@ pub enum DatabaseError {
#[error("An unknown error occurred")]
Others,
}

impl From<diesel::result::Error> for DatabaseError {
fn from(error: diesel::result::Error) -> Self {
match error {
diesel::result::Error::DatabaseError(
diesel::result::DatabaseErrorKind::UniqueViolation,
_,
) => Self::UniqueViolation,
diesel::result::Error::NotFound => Self::NotFound,
diesel::result::Error::QueryBuilderError(_) => Self::QueryGenerationFailed,
_ => Self::Others,
}
}
}
137 changes: 67 additions & 70 deletions crates/router/src/db/refund.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ mod storage {

#[cfg(feature = "kv_store")]
mod storage {
use common_utils::date_time;
use common_utils::{date_time, if_err_reverse_lookup};
use error_stack::{IntoReport, ResultExt};
use redis_interface::HsetnxReply;
use storage_impl::redis::kv_store::{kv_wrapper, KvOperation};
Expand All @@ -277,7 +277,6 @@ mod storage {
connection,
core::errors::{self, CustomResult},
db::reverse_lookup::ReverseLookupInterface,
logger,
services::Store,
types::storage::{self as storage_types, enums, kv},
utils::{self, db_utils},
Expand Down Expand Up @@ -305,9 +304,11 @@ mod storage {
enums::MerchantStorageScheme::PostgresOnly => database_call().await,
enums::MerchantStorageScheme::RedisKv => {
let lookup_id = format!("{merchant_id}_{internal_reference_id}");
let lookup = self
.get_lookup_by_lookup_id(&lookup_id, storage_scheme)
.await?;
let lookup = if_err_reverse_lookup!(
self.get_lookup_by_lookup_id(&lookup_id, storage_scheme)
.await,
database_call().await
);

let key = &lookup.pk_id;
Box::pin(db_utils::try_redis_get_else_try_database_get(
Expand Down Expand Up @@ -382,6 +383,50 @@ mod storage {
},
};

let mut reverse_lookups = vec![
storage_types::ReverseLookupNew {
sk_id: field.clone(),
lookup_id: format!(
"{}_{}",
created_refund.merchant_id, created_refund.refund_id
),
pk_id: key.clone(),
source: "refund".to_string(),
updated_by: storage_scheme.to_string(),
},
// [#492]: A discussion is required on whether this is required?
storage_types::ReverseLookupNew {
sk_id: field.clone(),
lookup_id: format!(
"{}_{}",
created_refund.merchant_id, created_refund.internal_reference_id
),
pk_id: key.clone(),
source: "refund".to_string(),
updated_by: storage_scheme.to_string(),
},
];
if let Some(connector_refund_id) = created_refund.to_owned().connector_refund_id
{
reverse_lookups.push(storage_types::ReverseLookupNew {
sk_id: field.clone(),
lookup_id: format!(
"{}_{}_{}",
created_refund.merchant_id,
connector_refund_id,
created_refund.connector
),
pk_id: key.clone(),
source: "refund".to_string(),
updated_by: storage_scheme.to_string(),
})
};
let rev_look = reverse_lookups
.into_iter()
.map(|rev| self.insert_reverse_lookup(rev, storage_scheme));

futures::future::try_join_all(rev_look).await?;

match kv_wrapper::<storage_types::Refund, _, _>(
self,
KvOperation::<storage_types::Refund>::HSetNx(
Expand All @@ -400,55 +445,7 @@ mod storage {
key: Some(created_refund.refund_id),
})
.into_report(),
Ok(HsetnxReply::KeySet) => {
let mut reverse_lookups = vec![
storage_types::ReverseLookupNew {
sk_id: field.clone(),
lookup_id: format!(
"{}_{}",
created_refund.merchant_id, created_refund.refund_id
),
pk_id: key.clone(),
source: "refund".to_string(),
updated_by: storage_scheme.to_string(),
},
// [#492]: A discussion is required on whether this is required?
storage_types::ReverseLookupNew {
sk_id: field.clone(),
lookup_id: format!(
"{}_{}",
created_refund.merchant_id,
created_refund.internal_reference_id
),
pk_id: key.clone(),
source: "refund".to_string(),
updated_by: storage_scheme.to_string(),
},
];
if let Some(connector_refund_id) =
created_refund.to_owned().connector_refund_id
{
reverse_lookups.push(storage_types::ReverseLookupNew {
sk_id: field.clone(),
lookup_id: format!(
"{}_{}_{}",
created_refund.merchant_id,
connector_refund_id,
created_refund.connector
),
pk_id: key,
source: "refund".to_string(),
updated_by: storage_scheme.to_string(),
})
};
let rev_look = reverse_lookups
.into_iter()
.map(|rev| self.insert_reverse_lookup(rev, storage_scheme));

futures::future::try_join_all(rev_look).await?;

Ok(created_refund)
}
Ok(HsetnxReply::KeySet) => Ok(created_refund),
Err(er) => Err(er).change_context(errors::StorageError::KVError),
}
}
Expand Down Expand Up @@ -476,16 +473,12 @@ mod storage {
enums::MerchantStorageScheme::PostgresOnly => database_call().await,
enums::MerchantStorageScheme::RedisKv => {
let lookup_id = format!("{merchant_id}_{connector_transaction_id}");
let lookup = match self
.get_lookup_by_lookup_id(&lookup_id, storage_scheme)
.await
{
Ok(l) => l,
Err(err) => {
logger::error!(?err);
return Ok(vec![]);
}
};
let lookup = if_err_reverse_lookup!(
self.get_lookup_by_lookup_id(&lookup_id, storage_scheme)
.await,
database_call().await
);

let key = &lookup.pk_id;

let pattern = db_utils::generate_hscan_pattern_for_refund(&lookup.sk_id);
Expand Down Expand Up @@ -576,9 +569,11 @@ mod storage {
enums::MerchantStorageScheme::PostgresOnly => database_call().await,
enums::MerchantStorageScheme::RedisKv => {
let lookup_id = format!("{merchant_id}_{refund_id}");
let lookup = self
.get_lookup_by_lookup_id(&lookup_id, storage_scheme)
.await?;
let lookup = if_err_reverse_lookup!(
self.get_lookup_by_lookup_id(&lookup_id, storage_scheme)
.await,
database_call().await
);

let key = &lookup.pk_id;
Box::pin(db_utils::try_redis_get_else_try_database_get(
Expand Down Expand Up @@ -621,9 +616,11 @@ mod storage {
enums::MerchantStorageScheme::PostgresOnly => database_call().await,
enums::MerchantStorageScheme::RedisKv => {
let lookup_id = format!("{merchant_id}_{connector_refund_id}_{connector}");
let lookup = self
.get_lookup_by_lookup_id(&lookup_id, storage_scheme)
.await?;
let lookup = if_err_reverse_lookup!(
self.get_lookup_by_lookup_id(&lookup_id, storage_scheme)
.await,
database_call().await
);

let key = &lookup.pk_id;
Box::pin(db_utils::try_redis_get_else_try_database_get(
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use storage_impl::errors::ApplicationResult;
use tokio::sync::{mpsc, oneshot};

pub use self::env::logger;
pub(crate) use self::macros::*;
use crate::{configs::settings, core::errors};

#[cfg(feature = "mimalloc")]
Expand Down
Loading

0 comments on commit ecae9fc

Please sign in to comment.