From c6d52d5dafd908b01395ffa4a06695df9bb4f1b8 Mon Sep 17 00:00:00 2001 From: Aprabhat19 Date: Wed, 29 May 2024 16:59:19 +0530 Subject: [PATCH 01/15] add moka cache for decision manager --- .../src/core/payments/conditional_configs.rs | 71 ++++--------------- 1 file changed, 12 insertions(+), 59 deletions(-) diff --git a/crates/router/src/core/payments/conditional_configs.rs b/crates/router/src/core/payments/conditional_configs.rs index 5dc78d42e5ea..f832f0790052 100644 --- a/crates/router/src/core/payments/conditional_configs.rs +++ b/crates/router/src/core/payments/conditional_configs.rs @@ -4,7 +4,7 @@ use api_models::{ conditional_configs::{ConditionalConfigs, DecisionManagerRecord}, routing, }; -use common_utils::{ext_traits::StringExt, static_cache::StaticCache}; +use common_utils::ext_traits::StringExt; use error_stack::ResultExt; use euclid::backend::{self, inputs as dsl_inputs, EuclidBackend}; use router_env::{instrument, tracing}; @@ -12,11 +12,11 @@ use router_env::{instrument, tracing}; use super::routing::make_dsl_input; use crate::{ core::{errors, errors::ConditionalConfigError as ConfigError, payments}, + db::cache, routes, }; -static CONF_CACHE: StaticCache> = - StaticCache::new(); +use storage_impl::redis::cache::ROUTING_CACHE; pub type ConditionalConfigResult = errors::CustomResult; #[instrument(skip_all)] @@ -31,73 +31,26 @@ pub async fn perform_decision_management( } else { return Ok(ConditionalConfigs::default()); }; - - let key = ensure_algorithm_cached( - state, - merchant_id, - algorithm_ref.timestamp, - algorithm_id.as_str(), - ) - .await?; - let cached_algo = CONF_CACHE - .retrieve(&key) - .change_context(ConfigError::CacheMiss) - .attach_printable("Unable to retrieve cached routing algorithm even after refresh")?; - let backend_input = - make_dsl_input(payment_data).change_context(ConfigError::InputConstructionError)?; - let interpreter = cached_algo.as_ref(); - execute_dsl_and_get_conditional_config(backend_input, interpreter).await -} - -#[instrument(skip_all)] -pub async fn ensure_algorithm_cached( - state: &routes::AppState, - merchant_id: &str, - timestamp: i64, - algorithm_id: &str, -) -> ConditionalConfigResult { let key = format!("dsl_{merchant_id}"); - let present = CONF_CACHE - .present(&key) - .change_context(ConfigError::DslCachePoisoned) - .attach_printable("Error checking presece of DSL")?; - let expired = CONF_CACHE - .expired(&key, timestamp) - .change_context(ConfigError::DslCachePoisoned) - .attach_printable("Error checking presence of DSL")?; - if !present || expired { - refresh_routing_cache(state, key.clone(), algorithm_id, timestamp).await?; - }; - Ok(key) -} - -#[instrument(skip_all)] -pub async fn refresh_routing_cache( - state: &routes::AppState, - key: String, - algorithm_id: &str, - timestamp: i64, -) -> ConditionalConfigResult<()> { - let config = state - .store - .find_config_by_key(algorithm_id) + let find_key_from_db = || async { state.store.find_config_by_key(&algorithm_id).await }; + let db = &*state.store; + let config = cache::get_or_populate_in_memory(db, &key, find_key_from_db, &ROUTING_CACHE) .await - .change_context(ConfigError::DslMissingInDb) - .attach_printable("Error parsing DSL from config")?; + .change_context(ConfigError::DslCachePoisoned)?; let rec: DecisionManagerRecord = config .config .parse_struct("Program") .change_context(ConfigError::DslParsingError) .attach_printable("Error parsing routing algorithm from configs")?; + let interpreter: backend::VirInterpreterBackend = backend::VirInterpreterBackend::with_program(rec.program) .change_context(ConfigError::DslBackendInitError) .attach_printable("Error initializing DSL interpreter backend")?; - CONF_CACHE - .save(key, interpreter, timestamp) - .change_context(ConfigError::DslCachePoisoned) - .attach_printable("Error saving DSL to cache")?; - Ok(()) + let backend_input = + make_dsl_input(payment_data).change_context(ConfigError::InputConstructionError)?; + + execute_dsl_and_get_conditional_config(backend_input, &interpreter).await } pub async fn execute_dsl_and_get_conditional_config( From 6f89a324016549ecb901ae100579d2a9e346794f Mon Sep 17 00:00:00 2001 From: Aprabhat19 Date: Wed, 29 May 2024 17:04:08 +0530 Subject: [PATCH 02/15] minor changes --- crates/router/src/core/payments/conditional_configs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/router/src/core/payments/conditional_configs.rs b/crates/router/src/core/payments/conditional_configs.rs index f832f0790052..c9159c4a83bd 100644 --- a/crates/router/src/core/payments/conditional_configs.rs +++ b/crates/router/src/core/payments/conditional_configs.rs @@ -32,8 +32,8 @@ pub async fn perform_decision_management( return Ok(ConditionalConfigs::default()); }; let key = format!("dsl_{merchant_id}"); - let find_key_from_db = || async { state.store.find_config_by_key(&algorithm_id).await }; let db = &*state.store; + let find_key_from_db = || async { db.find_config_by_key(&algorithm_id).await }; let config = cache::get_or_populate_in_memory(db, &key, find_key_from_db, &ROUTING_CACHE) .await .change_context(ConfigError::DslCachePoisoned)?; From 7f2bae1a551f9148d5d1a9bcedab60a4e6198b51 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 11:36:48 +0000 Subject: [PATCH 03/15] chore: run formatter --- crates/router/src/core/payments/conditional_configs.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/router/src/core/payments/conditional_configs.rs b/crates/router/src/core/payments/conditional_configs.rs index c9159c4a83bd..604be2b1d03a 100644 --- a/crates/router/src/core/payments/conditional_configs.rs +++ b/crates/router/src/core/payments/conditional_configs.rs @@ -8,6 +8,7 @@ use common_utils::ext_traits::StringExt; use error_stack::ResultExt; use euclid::backend::{self, inputs as dsl_inputs, EuclidBackend}; use router_env::{instrument, tracing}; +use storage_impl::redis::cache::ROUTING_CACHE; use super::routing::make_dsl_input; use crate::{ @@ -15,8 +16,6 @@ use crate::{ db::cache, routes, }; - -use storage_impl::redis::cache::ROUTING_CACHE; pub type ConditionalConfigResult = errors::CustomResult; #[instrument(skip_all)] From d02616a33c473e5c3f3acd612c9bc9f73824b779 Mon Sep 17 00:00:00 2001 From: Aprabhat19 Date: Thu, 30 May 2024 17:27:16 +0530 Subject: [PATCH 04/15] change the name of the cgraph cache --- crates/router/src/core/payments/routing.rs | 4 ++-- crates/router/src/db/merchant_account.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/router/src/core/payments/routing.rs b/crates/router/src/core/payments/routing.rs index d45f804268b3..210c5744dc32 100644 --- a/crates/router/src/core/payments/routing.rs +++ b/crates/router/src/core/payments/routing.rs @@ -547,9 +547,9 @@ pub async fn get_merchant_cgraph<'a>( #[cfg(not(feature = "business_profile_routing"))] let key = match transaction_type { - api_enums::TransactionType::Payment => format!("kgraph_{}", merchant_id), + api_enums::TransactionType::Payment => format!("cgraph_{}", merchant_id), #[cfg(feature = "payouts")] - api_enums::TransactionType::Payout => format!("kgraph_po_{}", merchant_id), + api_enums::TransactionType::Payout => format!("cgraph_po_{}", merchant_id), }; let cached_cgraph = CGRAPH_CACHE diff --git a/crates/router/src/db/merchant_account.rs b/crates/router/src/db/merchant_account.rs index 9b82ef414ce8..1487e560a783 100644 --- a/crates/router/src/db/merchant_account.rs +++ b/crates/router/src/db/merchant_account.rs @@ -517,7 +517,7 @@ async fn publish_and_redact_merchant_account_cache( let kgraph_key = merchant_account.default_profile.as_ref().map(|profile_id| { CacheKind::CGraph( format!( - "kgraph_{}_{}", + "cgraph_{}_{}", merchant_account.merchant_id.clone(), profile_id, ) @@ -527,7 +527,7 @@ async fn publish_and_redact_merchant_account_cache( #[cfg(not(feature = "business_profile_routing"))] let kgraph_key = Some(CacheKind::CGraph( - format!("kgraph_{}", merchant_account.merchant_id.clone()).into(), + format!("cgraph_{}", merchant_account.merchant_id.clone()).into(), )); let mut cache_keys = vec![CacheKind::Accounts( From 10c04ace3abf96df6dcb0f50b07767109ca3bf62 Mon Sep 17 00:00:00 2001 From: Aprabhat19 Date: Fri, 31 May 2024 13:25:16 +0530 Subject: [PATCH 05/15] cache the Vir Program, instead of the config --- crates/euclid/src/backend/vir_interpreter.rs | 3 ++ crates/euclid/src/frontend/vir.rs | 12 ++++--- crates/euclid/src/types.rs | 12 +++---- .../src/core/payments/conditional_configs.rs | 32 +++++++++++++------ crates/storage_impl/src/redis/cache.rs | 8 +++++ 5 files changed, 47 insertions(+), 20 deletions(-) diff --git a/crates/euclid/src/backend/vir_interpreter.rs b/crates/euclid/src/backend/vir_interpreter.rs index b7be62cf6740..c5d998927124 100644 --- a/crates/euclid/src/backend/vir_interpreter.rs +++ b/crates/euclid/src/backend/vir_interpreter.rs @@ -8,7 +8,10 @@ use crate::{ vir, }, }; +use serde::{Deserialize, Serialize}; +use std::fmt::Debug; +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct VirInterpreterBackend { program: vir::ValuedProgram, } diff --git a/crates/euclid/src/frontend/vir.rs b/crates/euclid/src/frontend/vir.rs index 750ff4e61ff8..6c8bc7ab2f16 100644 --- a/crates/euclid/src/frontend/vir.rs +++ b/crates/euclid/src/frontend/vir.rs @@ -1,13 +1,15 @@ //! Valued Intermediate Representation +use serde::{Deserialize, Serialize}; + use crate::types::{EuclidValue, Metadata}; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum ValuedComparisonLogic { NegativeConjunction, PositiveDisjunction, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct ValuedComparison { pub values: Vec, pub logic: ValuedComparisonLogic, @@ -16,20 +18,20 @@ pub struct ValuedComparison { pub type ValuedIfCondition = Vec; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct ValuedIfStatement { pub condition: ValuedIfCondition, pub nested: Option>, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct ValuedRule { pub name: String, pub connector_selection: O, pub statements: Vec, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct ValuedProgram { pub default_selection: O, pub rules: Vec>, diff --git a/crates/euclid/src/types.rs b/crates/euclid/src/types.rs index 904525d54b73..05d3fe6bb8e6 100644 --- a/crates/euclid/src/types.rs +++ b/crates/euclid/src/types.rs @@ -1,7 +1,7 @@ pub mod transformers; use euclid_macros::EnumNums; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use strum::VariantNames; use crate::{ @@ -143,7 +143,7 @@ impl EuclidKey { enums::collect_variants!(EuclidKey); -#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] #[serde(rename_all = "snake_case")] pub enum NumValueRefinement { NotEqual, @@ -178,18 +178,18 @@ impl From for ast::ComparisonType { } } -#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, serde::Serialize)] +#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] pub struct StrValue { pub value: String, } -#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, serde::Serialize)] +#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] pub struct MetadataValue { pub key: String, pub value: String, } -#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, serde::Serialize)] +#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] pub struct NumValue { pub number: i64, pub refinement: Option, @@ -234,7 +234,7 @@ impl NumValue { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum EuclidValue { PaymentMethod(enums::PaymentMethod), CardBin(StrValue), diff --git a/crates/router/src/core/payments/conditional_configs.rs b/crates/router/src/core/payments/conditional_configs.rs index 604be2b1d03a..37ab17e39baf 100644 --- a/crates/router/src/core/payments/conditional_configs.rs +++ b/crates/router/src/core/payments/conditional_configs.rs @@ -8,12 +8,11 @@ use common_utils::ext_traits::StringExt; use error_stack::ResultExt; use euclid::backend::{self, inputs as dsl_inputs, EuclidBackend}; use router_env::{instrument, tracing}; -use storage_impl::redis::cache::ROUTING_CACHE; +use storage_impl::redis::cache::{self, DECISION_MANAGER_CACHE}; use super::routing::make_dsl_input; use crate::{ core::{errors, errors::ConditionalConfigError as ConfigError, payments}, - db::cache, routes, }; pub type ConditionalConfigResult = errors::CustomResult; @@ -30,22 +29,37 @@ pub async fn perform_decision_management( } else { return Ok(ConditionalConfigs::default()); }; - let key = format!("dsl_{merchant_id}"); let db = &*state.store; - let find_key_from_db = || async { db.find_config_by_key(&algorithm_id).await }; - let config = cache::get_or_populate_in_memory(db, &key, find_key_from_db, &ROUTING_CACHE) + + let key = format!("dsl_{merchant_id}"); + + let config = db + .find_config_by_key(&algorithm_id) .await - .change_context(ConfigError::DslCachePoisoned)?; + .change_context(ConfigError::DslMissingInDb) + .attach_printable("Missing the config in db")?; + let rec: DecisionManagerRecord = config .config .parse_struct("Program") .change_context(ConfigError::DslParsingError) .attach_printable("Error parsing routing algorithm from configs")?; - let interpreter: backend::VirInterpreterBackend = + let find_key_from_db = || async { backend::VirInterpreterBackend::with_program(rec.program) - .change_context(ConfigError::DslBackendInitError) - .attach_printable("Error initializing DSL interpreter backend")?; + .change_context(errors::StorageError::ValueNotFound("Program".to_string())) + .attach_printable("Error initializing DSL interpreter backend") + }; + + let interpreter = cache::get_or_populate_in_memory( + db.get_cache_store().as_ref(), + &key, + find_key_from_db, + &DECISION_MANAGER_CACHE, + ) + .await + .change_context(ConfigError::DslCachePoisoned)?; + let backend_input = make_dsl_input(payment_data).change_context(ConfigError::InputConstructionError)?; diff --git a/crates/storage_impl/src/redis/cache.rs b/crates/storage_impl/src/redis/cache.rs index 68f04936daf5..f0adc6a5af5d 100644 --- a/crates/storage_impl/src/redis/cache.rs +++ b/crates/storage_impl/src/redis/cache.rs @@ -57,6 +57,14 @@ pub static ACCOUNTS_CACHE: Lazy = pub static ROUTING_CACHE: Lazy = Lazy::new(|| Cache::new(CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY))); +/// 3DS Decision Manager Cache +pub static DECISION_MANAGER_CACHE: Lazy = + Lazy::new(|| Cache::new(CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY))); + +/// Surcharge Cache +pub static SURCHARGE_CACHE: Lazy = + Lazy::new(|| Cache::new(CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY))); + /// CGraph Cache pub static CGRAPH_CACHE: Lazy = Lazy::new(|| Cache::new(CACHE_TTL, CACHE_TTI, Some(MAX_CAPACITY))); From 529bce7f266d92948128ed79c336035497bccbf2 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Fri, 31 May 2024 07:57:33 +0000 Subject: [PATCH 06/15] chore: run formatter --- crates/euclid/src/backend/vir_interpreter.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/euclid/src/backend/vir_interpreter.rs b/crates/euclid/src/backend/vir_interpreter.rs index c5d998927124..b8d14e228aa2 100644 --- a/crates/euclid/src/backend/vir_interpreter.rs +++ b/crates/euclid/src/backend/vir_interpreter.rs @@ -1,5 +1,9 @@ pub mod types; +use std::fmt::Debug; + +use serde::{Deserialize, Serialize}; + use crate::{ backend::{self, inputs, EuclidBackend}, frontend::{ @@ -8,8 +12,6 @@ use crate::{ vir, }, }; -use serde::{Deserialize, Serialize}; -use std::fmt::Debug; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct VirInterpreterBackend { From e08d9b70132b2942d73f1a9ac659f316a410e02d Mon Sep 17 00:00:00 2001 From: Aprabhat19 Date: Fri, 31 May 2024 18:33:02 +0530 Subject: [PATCH 07/15] cache the surcharge configs as well --- .../surcharge_decision_configs.rs | 113 +++++++----------- 1 file changed, 40 insertions(+), 73 deletions(-) diff --git a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs index 76881950e3bf..8f97623f4fe8 100644 --- a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs +++ b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs @@ -1,21 +1,6 @@ -use std::sync::Arc; - -use api_models::{ - payment_methods::SurchargeDetailsResponse, - payments, routing, - surcharge_decision_configs::{self, SurchargeDecisionConfigs, SurchargeDecisionManagerRecord}, -}; -use common_utils::{ext_traits::StringExt, static_cache::StaticCache, types as common_utils_types}; -use error_stack::{self, ResultExt}; -use euclid::{ - backend, - backend::{inputs as dsl_inputs, EuclidBackend}, -}; -use router_env::{instrument, tracing}; - use crate::{ core::{ - errors::ConditionalConfigError as ConfigError, + errors::{self, ConditionalConfigError as ConfigError}, payments::{ conditional_configs::ConditionalConfigResult, routing::make_dsl_input_for_surcharge, types, PaymentData, @@ -28,9 +13,22 @@ use crate::{ }, AppState, }; +use api_models::{ + payment_methods::SurchargeDetailsResponse, + payments, routing, + surcharge_decision_configs::{self, SurchargeDecisionConfigs, SurchargeDecisionManagerRecord}, +}; +use common_utils::{ext_traits::StringExt, types as common_utils_types}; +use error_stack::{self, ResultExt}; +use euclid::{ + backend, + backend::{inputs as dsl_inputs, EuclidBackend}, +}; +use router_env::{instrument, tracing}; +use serde::{Deserialize, Serialize}; +use storage_impl::redis::cache::{self, SURCHARGE_CACHE}; -static CONF_CACHE: StaticCache = StaticCache::new(); - +#[derive(Debug, Serialize, Deserialize, Clone)] struct VirInterpreterBackendCacheWrapper { cached_algorithm: backend::VirInterpreterBackend, merchant_surcharge_configs: surcharge_decision_configs::MerchantSurchargeConfigs, @@ -53,7 +51,7 @@ impl TryFrom for VirInterpreterBackendCacheWrapp enum SurchargeSource { /// Surcharge will be generated through the surcharge rules - Generate(Arc), + Generate(VirInterpreterBackendCacheWrapper), /// Surcharge is predefined by the merchant through payment create request Predetermined(payments::RequestSurchargeDetails), } @@ -116,19 +114,13 @@ pub async fn perform_surcharge_decision_management_for_payment_method_list( surcharge_decision_configs::MerchantSurchargeConfigs::default(), ), (None, Some(algorithm_id)) => { - let key = ensure_algorithm_cached( + let cached_algo = ensure_algorithm_cached( &*state.store, &payment_attempt.merchant_id, - algorithm_ref.timestamp, algorithm_id.as_str(), ) .await?; - let cached_algo = CONF_CACHE - .retrieve(&key) - .change_context(ConfigError::CacheMiss) - .attach_printable( - "Unable to retrieve cached routing algorithm even after refresh", - )?; + let merchant_surcharge_config = cached_algo.merchant_surcharge_configs.clone(); ( SurchargeSource::Generate(cached_algo), @@ -233,19 +225,13 @@ where SurchargeSource::Predetermined(request_surcharge_details) } (None, Some(algorithm_id)) => { - let key = ensure_algorithm_cached( + let cached_algo = ensure_algorithm_cached( &*state.store, &payment_data.payment_attempt.merchant_id, - algorithm_ref.timestamp, algorithm_id.as_str(), ) .await?; - let cached_algo = CONF_CACHE - .retrieve(&key) - .change_context(ConfigError::CacheMiss) - .attach_printable( - "Unable to retrieve cached routing algorithm even after refresh", - )?; + SurchargeSource::Generate(cached_algo) } (None, None) => return Ok(surcharge_metadata), @@ -291,19 +277,13 @@ pub async fn perform_surcharge_decision_management_for_saved_cards( SurchargeSource::Predetermined(request_surcharge_details) } (None, Some(algorithm_id)) => { - let key = ensure_algorithm_cached( + let cached_algo = ensure_algorithm_cached( &*state.store, &payment_attempt.merchant_id, - algorithm_ref.timestamp, algorithm_id.as_str(), ) .await?; - let cached_algo = CONF_CACHE - .retrieve(&key) - .change_context(ConfigError::CacheMiss) - .attach_printable( - "Unable to retrieve cached routing algorithm even after refresh", - )?; + SurchargeSource::Generate(cached_algo) } (None, None) => return Ok(surcharge_metadata), @@ -388,33 +368,11 @@ fn get_surcharge_details_from_surcharge_output( pub async fn ensure_algorithm_cached( store: &dyn StorageInterface, merchant_id: &str, - timestamp: i64, algorithm_id: &str, -) -> ConditionalConfigResult { +) -> ConditionalConfigResult { let key = format!("surcharge_dsl_{merchant_id}"); - let present = CONF_CACHE - .present(&key) - .change_context(ConfigError::DslCachePoisoned) - .attach_printable("Error checking presence of DSL")?; - let expired = CONF_CACHE - .expired(&key, timestamp) - .change_context(ConfigError::DslCachePoisoned) - .attach_printable("Error checking presence of DSL")?; - if !present || expired { - refresh_surcharge_algorithm_cache(store, key.clone(), algorithm_id, timestamp).await? - } - Ok(key) -} - -#[instrument(skip_all)] -pub async fn refresh_surcharge_algorithm_cache( - store: &dyn StorageInterface, - key: String, - algorithm_id: &str, - timestamp: i64, -) -> ConditionalConfigResult<()> { - let config = store + let config: diesel_models::Config = store .find_config_by_key(algorithm_id) .await .change_context(ConfigError::DslMissingInDb) @@ -424,12 +382,21 @@ pub async fn refresh_surcharge_algorithm_cache( .parse_struct("Program") .change_context(ConfigError::DslParsingError) .attach_printable("Error parsing routing algorithm from configs")?; - let value_to_cache = VirInterpreterBackendCacheWrapper::try_from(record)?; - CONF_CACHE - .save(key, value_to_cache, timestamp) - .change_context(ConfigError::DslCachePoisoned) - .attach_printable("Error saving DSL to cache")?; - Ok(()) + let value_to_cache = || async { + VirInterpreterBackendCacheWrapper::try_from(record) + .change_context(errors::StorageError::ValueNotFound("Program".to_string())) + .attach_printable("Error initializing DSL interpreter backend") + }; + let interpreter = cache::get_or_populate_in_memory( + store.get_cache_store().as_ref(), + &key, + value_to_cache, + &SURCHARGE_CACHE, + ) + .await + .change_context(ConfigError::CacheMiss) + .attach_printable("Unable to retrieve cached routing algorithm even after refresh")?; + Ok(interpreter) } pub fn execute_dsl_and_get_conditional_config( From 9354bcc245f9704bb79dd3c8caa25a514600708a Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Fri, 31 May 2024 13:03:41 +0000 Subject: [PATCH 08/15] chore: run formatter --- .../surcharge_decision_configs.rs | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs index 8f97623f4fe8..56651c735cce 100644 --- a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs +++ b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs @@ -1,3 +1,18 @@ +use api_models::{ + payment_methods::SurchargeDetailsResponse, + payments, routing, + surcharge_decision_configs::{self, SurchargeDecisionConfigs, SurchargeDecisionManagerRecord}, +}; +use common_utils::{ext_traits::StringExt, types as common_utils_types}; +use error_stack::{self, ResultExt}; +use euclid::{ + backend, + backend::{inputs as dsl_inputs, EuclidBackend}, +}; +use router_env::{instrument, tracing}; +use serde::{Deserialize, Serialize}; +use storage_impl::redis::cache::{self, SURCHARGE_CACHE}; + use crate::{ core::{ errors::{self, ConditionalConfigError as ConfigError}, @@ -13,20 +28,6 @@ use crate::{ }, AppState, }; -use api_models::{ - payment_methods::SurchargeDetailsResponse, - payments, routing, - surcharge_decision_configs::{self, SurchargeDecisionConfigs, SurchargeDecisionManagerRecord}, -}; -use common_utils::{ext_traits::StringExt, types as common_utils_types}; -use error_stack::{self, ResultExt}; -use euclid::{ - backend, - backend::{inputs as dsl_inputs, EuclidBackend}, -}; -use router_env::{instrument, tracing}; -use serde::{Deserialize, Serialize}; -use storage_impl::redis::cache::{self, SURCHARGE_CACHE}; #[derive(Debug, Serialize, Deserialize, Clone)] struct VirInterpreterBackendCacheWrapper { From f11943806b546e0c863200aa2370c4ac960c173e Mon Sep 17 00:00:00 2001 From: Aprabhat19 Date: Mon, 3 Jun 2024 14:42:28 +0530 Subject: [PATCH 09/15] make struct VirInterpreter as public --- .../src/core/payment_methods/surcharge_decision_configs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs index 8f97623f4fe8..da348559834f 100644 --- a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs +++ b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs @@ -29,7 +29,7 @@ use serde::{Deserialize, Serialize}; use storage_impl::redis::cache::{self, SURCHARGE_CACHE}; #[derive(Debug, Serialize, Deserialize, Clone)] -struct VirInterpreterBackendCacheWrapper { +pub struct VirInterpreterBackendCacheWrapper { cached_algorithm: backend::VirInterpreterBackend, merchant_surcharge_configs: surcharge_decision_configs::MerchantSurchargeConfigs, } From 06e2830e200835cea04ba8be2a01f43b568225ee Mon Sep 17 00:00:00 2001 From: Aprabhat19 Date: Wed, 5 Jun 2024 12:29:48 +0530 Subject: [PATCH 10/15] address comments --- .../surcharge_decision_configs.rs | 20 ++++++++--------- .../src/core/payments/conditional_configs.rs | 22 +++++++++---------- crates/router/src/db/merchant_account.rs | 6 ++--- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs index 08d8a0b2fd3f..8513f3fde43d 100644 --- a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs +++ b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs @@ -373,17 +373,17 @@ pub async fn ensure_algorithm_cached( ) -> ConditionalConfigResult { let key = format!("surcharge_dsl_{merchant_id}"); - let config: diesel_models::Config = store - .find_config_by_key(algorithm_id) - .await - .change_context(ConfigError::DslMissingInDb) - .attach_printable("Error parsing DSL from config")?; - let record: SurchargeDecisionManagerRecord = config - .config - .parse_struct("Program") - .change_context(ConfigError::DslParsingError) - .attach_printable("Error parsing routing algorithm from configs")?; let value_to_cache = || async { + let config: diesel_models::Config = store + .find_config_by_key(algorithm_id) + .await + .change_context(ConfigError::DslMissingInDb) + .attach_printable("Error parsing DSL from config")?; + let record: SurchargeDecisionManagerRecord = config + .config + .parse_struct("Program") + .change_context(ConfigError::DslParsingError) + .attach_printable("Error parsing routing algorithm from configs")?; VirInterpreterBackendCacheWrapper::try_from(record) .change_context(errors::StorageError::ValueNotFound("Program".to_string())) .attach_printable("Error initializing DSL interpreter backend") diff --git a/crates/router/src/core/payments/conditional_configs.rs b/crates/router/src/core/payments/conditional_configs.rs index 37ab17e39baf..839f03044bac 100644 --- a/crates/router/src/core/payments/conditional_configs.rs +++ b/crates/router/src/core/payments/conditional_configs.rs @@ -33,19 +33,19 @@ pub async fn perform_decision_management( let key = format!("dsl_{merchant_id}"); - let config = db - .find_config_by_key(&algorithm_id) - .await - .change_context(ConfigError::DslMissingInDb) - .attach_printable("Missing the config in db")?; + let find_key_from_db = || async { + let config = db + .find_config_by_key(&algorithm_id) + .await + .change_context(ConfigError::DslMissingInDb) + .attach_printable("Missing the config in db")?; - let rec: DecisionManagerRecord = config - .config - .parse_struct("Program") - .change_context(ConfigError::DslParsingError) - .attach_printable("Error parsing routing algorithm from configs")?; + let rec: DecisionManagerRecord = config + .config + .parse_struct("Program") + .change_context(ConfigError::DslParsingError) + .attach_printable("Error parsing routing algorithm from configs")?; - let find_key_from_db = || async { backend::VirInterpreterBackend::with_program(rec.program) .change_context(errors::StorageError::ValueNotFound("Program".to_string())) .attach_printable("Error initializing DSL interpreter backend") diff --git a/crates/router/src/db/merchant_account.rs b/crates/router/src/db/merchant_account.rs index 1487e560a783..39d63080a4b0 100644 --- a/crates/router/src/db/merchant_account.rs +++ b/crates/router/src/db/merchant_account.rs @@ -514,7 +514,7 @@ async fn publish_and_redact_merchant_account_cache( .map(|publishable_key| CacheKind::Accounts(publishable_key.into())); #[cfg(feature = "business_profile_routing")] - let kgraph_key = merchant_account.default_profile.as_ref().map(|profile_id| { + let cgraph_key = merchant_account.default_profile.as_ref().map(|profile_id| { CacheKind::CGraph( format!( "cgraph_{}_{}", @@ -526,7 +526,7 @@ async fn publish_and_redact_merchant_account_cache( }); #[cfg(not(feature = "business_profile_routing"))] - let kgraph_key = Some(CacheKind::CGraph( + let cgraph_key = Some(CacheKind::CGraph( format!("cgraph_{}", merchant_account.merchant_id.clone()).into(), )); @@ -535,7 +535,7 @@ async fn publish_and_redact_merchant_account_cache( )]; cache_keys.extend(publishable_key.into_iter()); - cache_keys.extend(kgraph_key.into_iter()); + cache_keys.extend(cgraph_key.into_iter()); cache::publish_into_redact_channel(store.get_cache_store().as_ref(), cache_keys).await?; Ok(()) From 1604e92f0a7b0f53f428e89a95dd3a8ee9eb1c4d Mon Sep 17 00:00:00 2001 From: Aprabhat19 Date: Thu, 6 Jun 2024 15:29:06 +0530 Subject: [PATCH 11/15] invalidate the cache for decision manager as well as surcharge --- crates/router/src/core/conditional_config.rs | 10 +++++----- crates/router/src/core/routing.rs | 7 +++++-- crates/router/src/core/routing/helpers.rs | 8 +++++++- crates/router/src/core/surcharge_decision_config.rs | 10 +++++----- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/crates/router/src/core/conditional_config.rs b/crates/router/src/core/conditional_config.rs index a8bc8a797dc3..e27232a888bb 100644 --- a/crates/router/src/core/conditional_config.rs +++ b/crates/router/src/core/conditional_config.rs @@ -99,8 +99,8 @@ pub async fn upsert_conditional_config( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Error serializing the config")?; - algo_id.update_conditional_config_id(key); - update_merchant_active_algorithm_ref(db, &key_store, algo_id) + algo_id.update_conditional_config_id(key.clone()); + update_merchant_active_algorithm_ref(db, &key_store, &key, algo_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update routing algorithm ref")?; @@ -134,8 +134,8 @@ pub async fn upsert_conditional_config( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Error fetching the config")?; - algo_id.update_conditional_config_id(key); - update_merchant_active_algorithm_ref(db, &key_store, algo_id) + algo_id.update_conditional_config_id(key.clone()); + update_merchant_active_algorithm_ref(db, &key_store, &key, algo_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update routing algorithm ref")?; @@ -164,7 +164,7 @@ pub async fn delete_conditional_config( .attach_printable("Could not decode the conditional_config algorithm")? .unwrap_or_default(); algo_id.config_algo_id = None; - update_merchant_active_algorithm_ref(db, &key_store, algo_id) + update_merchant_active_algorithm_ref(db, &key_store, &key, algo_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update deleted algorithm ref")?; diff --git a/crates/router/src/core/routing.rs b/crates/router/src/core/routing.rs index a64dadaa35d9..352e9f9b7b79 100644 --- a/crates/router/src/core/routing.rs +++ b/crates/router/src/core/routing.rs @@ -232,7 +232,9 @@ pub async fn create_routing_config( if records_are_empty { merchant_dictionary.active_id = Some(algorithm_id.clone()); algorithm_ref.update_algorithm_id(algorithm_id); - helpers::update_merchant_active_algorithm_ref(db, &key_store, algorithm_ref).await?; + let key = format!("dsl_{merchant_id}"); + helpers::update_merchant_active_algorithm_ref(db, &key_store, &key, algorithm_ref) + .await?; } helpers::update_merchant_routing_dictionary( @@ -363,7 +365,8 @@ pub async fn link_routing_config( merchant_dictionary, ) .await?; - helpers::update_merchant_active_algorithm_ref(db, &key_store, routing_ref).await?; + let key = format!("dsl_{merchant_id}"); + helpers::update_merchant_active_algorithm_ref(db, &key_store, &key, routing_ref).await?; metrics::ROUTING_LINK_CONFIG_SUCCESS_RESPONSE.add(&metrics::CONTEXT, 1, &[]); Ok(service_api::ApplicationResponse::Json(response)) diff --git a/crates/router/src/core/routing/helpers.rs b/crates/router/src/core/routing/helpers.rs index 2e1032e8e4cd..99da36a4b1fe 100644 --- a/crates/router/src/core/routing/helpers.rs +++ b/crates/router/src/core/routing/helpers.rs @@ -188,6 +188,7 @@ pub async fn update_routing_algorithm( pub async fn update_merchant_active_algorithm_ref( db: &dyn StorageInterface, key_store: &domain::MerchantKeyStore, + key: &str, algorithm_id: routing_types::RoutingAlgorithmRef, ) -> RouterResult<()> { let ref_value = algorithm_id @@ -216,7 +217,7 @@ pub async fn update_merchant_active_algorithm_ref( default_profile: None, payment_link_config: None, }; - + let config_key = cache::CacheKind::Config(key.into()); db.update_specific_fields_in_merchant( &key_store.merchant_id, merchant_account_update, @@ -226,6 +227,11 @@ pub async fn update_merchant_active_algorithm_ref( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update routing algorithm ref in merchant account")?; + cache::publish_into_redact_channel(db.get_cache_store().as_ref(), [config_key]) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to invalidate the config cache")?; + Ok(()) } diff --git a/crates/router/src/core/surcharge_decision_config.rs b/crates/router/src/core/surcharge_decision_config.rs index 7f451e6008fe..bcf3d4cfb67b 100644 --- a/crates/router/src/core/surcharge_decision_config.rs +++ b/crates/router/src/core/surcharge_decision_config.rs @@ -88,8 +88,8 @@ pub async fn upsert_surcharge_decision_config( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Error serializing the config")?; - algo_id.update_surcharge_config_id(key); - update_merchant_active_algorithm_ref(db, &key_store, algo_id) + algo_id.update_surcharge_config_id(key.clone()); + update_merchant_active_algorithm_ref(db, &key_store, &key, algo_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update routing algorithm ref")?; @@ -124,8 +124,8 @@ pub async fn upsert_surcharge_decision_config( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Error fetching the config")?; - algo_id.update_surcharge_config_id(key); - update_merchant_active_algorithm_ref(db, &key_store, algo_id) + algo_id.update_surcharge_config_id(key.clone()); + update_merchant_active_algorithm_ref(db, &key_store, &key, algo_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update routing algorithm ref")?; @@ -154,7 +154,7 @@ pub async fn delete_surcharge_decision_config( .attach_printable("Could not decode the surcharge conditional_config algorithm")? .unwrap_or_default(); algo_id.surcharge_config_algo_id = None; - update_merchant_active_algorithm_ref(db, &key_store, algo_id) + update_merchant_active_algorithm_ref(db, &key_store, &key, algo_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update deleted algorithm ref")?; From ba4ce6565802a34c0209a7c5880d6780dfd3c27e Mon Sep 17 00:00:00 2001 From: Aprabhat19 Date: Fri, 7 Jun 2024 12:04:04 +0530 Subject: [PATCH 12/15] introduce DecisionManger and Surcharge cache kinds --- crates/router/src/core/conditional_config.rs | 27 +++++++------ crates/router/src/core/routing.rs | 38 ++++++++++--------- crates/router/src/core/routing/helpers.rs | 4 +- .../src/core/surcharge_decision_config.rs | 31 ++++++++------- crates/storage_impl/src/redis/cache.rs | 15 ++++++++ crates/storage_impl/src/redis/pub_sub.rs | 35 ++++++++++++++++- 6 files changed, 102 insertions(+), 48 deletions(-) diff --git a/crates/router/src/core/conditional_config.rs b/crates/router/src/core/conditional_config.rs index e27232a888bb..65b0eab70b3f 100644 --- a/crates/router/src/core/conditional_config.rs +++ b/crates/router/src/core/conditional_config.rs @@ -1,12 +1,3 @@ -use api_models::{ - conditional_configs::{DecisionManager, DecisionManagerRecord, DecisionManagerResponse}, - routing, -}; -use common_utils::ext_traits::{Encode, StringExt, ValueExt}; -use diesel_models::configs; -use error_stack::ResultExt; -use euclid::frontend::ast; - use super::routing::helpers::{ get_payment_config_routing_id, update_merchant_active_algorithm_ref, }; @@ -17,6 +8,15 @@ use crate::{ types::domain, utils::OptionExt, }; +use api_models::{ + conditional_configs::{DecisionManager, DecisionManagerRecord, DecisionManagerResponse}, + routing, +}; +use common_utils::ext_traits::{Encode, StringExt, ValueExt}; +use diesel_models::configs; +use error_stack::ResultExt; +use euclid::frontend::ast; +use storage_impl::redis::cache; pub async fn upsert_conditional_config( state: SessionState, @@ -100,7 +100,8 @@ pub async fn upsert_conditional_config( .attach_printable("Error serializing the config")?; algo_id.update_conditional_config_id(key.clone()); - update_merchant_active_algorithm_ref(db, &key_store, &key, algo_id) + let config_key = cache::CacheKind::DecisionManager(key.into()); + update_merchant_active_algorithm_ref(db, &key_store, config_key, algo_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update routing algorithm ref")?; @@ -135,7 +136,8 @@ pub async fn upsert_conditional_config( .attach_printable("Error fetching the config")?; algo_id.update_conditional_config_id(key.clone()); - update_merchant_active_algorithm_ref(db, &key_store, &key, algo_id) + let config_key = cache::CacheKind::DecisionManager(key.into()); + update_merchant_active_algorithm_ref(db, &key_store, config_key, algo_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update routing algorithm ref")?; @@ -164,7 +166,8 @@ pub async fn delete_conditional_config( .attach_printable("Could not decode the conditional_config algorithm")? .unwrap_or_default(); algo_id.config_algo_id = None; - update_merchant_active_algorithm_ref(db, &key_store, &key, algo_id) + let config_key = cache::CacheKind::DecisionManager(key.clone().into()); + update_merchant_active_algorithm_ref(db, &key_store, config_key, algo_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update deleted algorithm ref")?; diff --git a/crates/router/src/core/routing.rs b/crates/router/src/core/routing.rs index 352e9f9b7b79..766aeba6629c 100644 --- a/crates/router/src/core/routing.rs +++ b/crates/router/src/core/routing.rs @@ -1,21 +1,6 @@ pub mod helpers; pub mod transformers; -#[cfg(feature = "business_profile_routing")] -use api_models::routing::{RoutingRetrieveLinkQuery, RoutingRetrieveQuery}; -use api_models::{ - enums, - routing::{self as routing_types, RoutingAlgorithmId}, -}; -#[cfg(not(feature = "business_profile_routing"))] -use common_utils::ext_traits::{Encode, StringExt}; -#[cfg(not(feature = "business_profile_routing"))] -use diesel_models::configs; -#[cfg(feature = "business_profile_routing")] -use diesel_models::routing_algorithm::RoutingAlgorithm; -use error_stack::ResultExt; -use rustc_hash::FxHashSet; - use super::payments; #[cfg(feature = "payouts")] use super::payouts; @@ -35,6 +20,22 @@ use crate::{ use crate::{core::errors, services::api as service_api, types::storage}; #[cfg(feature = "business_profile_routing")] use crate::{errors, services::api as service_api}; +#[cfg(feature = "business_profile_routing")] +use api_models::routing::{RoutingRetrieveLinkQuery, RoutingRetrieveQuery}; +use api_models::{ + enums, + routing::{self as routing_types, RoutingAlgorithmId}, +}; +#[cfg(not(feature = "business_profile_routing"))] +use common_utils::ext_traits::{Encode, StringExt}; +#[cfg(not(feature = "business_profile_routing"))] +use diesel_models::configs; +#[cfg(feature = "business_profile_routing")] +use diesel_models::routing_algorithm::RoutingAlgorithm; +use error_stack::ResultExt; +use rustc_hash::FxHashSet; +#[cfg(not(feature = "business_profile_routing"))] +use storage_impl::redis::cache; pub enum TransactionData<'a, F> where @@ -232,7 +233,8 @@ pub async fn create_routing_config( if records_are_empty { merchant_dictionary.active_id = Some(algorithm_id.clone()); algorithm_ref.update_algorithm_id(algorithm_id); - let key = format!("dsl_{merchant_id}"); + let key = cache::CacheKind::Routing(format!("dsl_{merchant_id}").into()); + helpers::update_merchant_active_algorithm_ref(db, &key_store, &key, algorithm_ref) .await?; } @@ -365,8 +367,8 @@ pub async fn link_routing_config( merchant_dictionary, ) .await?; - let key = format!("dsl_{merchant_id}"); - helpers::update_merchant_active_algorithm_ref(db, &key_store, &key, routing_ref).await?; + let key = cache::CacheKind::Routing(format!("dsl_{merchant_id}").into()); + helpers::update_merchant_active_algorithm_ref(db, &key_store, key, routing_ref).await?; metrics::ROUTING_LINK_CONFIG_SUCCESS_RESPONSE.add(&metrics::CONTEXT, 1, &[]); Ok(service_api::ApplicationResponse::Json(response)) diff --git a/crates/router/src/core/routing/helpers.rs b/crates/router/src/core/routing/helpers.rs index 99da36a4b1fe..c89eb2b85793 100644 --- a/crates/router/src/core/routing/helpers.rs +++ b/crates/router/src/core/routing/helpers.rs @@ -188,7 +188,7 @@ pub async fn update_routing_algorithm( pub async fn update_merchant_active_algorithm_ref( db: &dyn StorageInterface, key_store: &domain::MerchantKeyStore, - key: &str, + config_key: cache::CacheKind<'_>, algorithm_id: routing_types::RoutingAlgorithmRef, ) -> RouterResult<()> { let ref_value = algorithm_id @@ -217,7 +217,7 @@ pub async fn update_merchant_active_algorithm_ref( default_profile: None, payment_link_config: None, }; - let config_key = cache::CacheKind::Config(key.into()); + db.update_specific_fields_in_merchant( &key_store.merchant_id, merchant_account_update, diff --git a/crates/router/src/core/surcharge_decision_config.rs b/crates/router/src/core/surcharge_decision_config.rs index bcf3d4cfb67b..f3b39d85cdc1 100644 --- a/crates/router/src/core/surcharge_decision_config.rs +++ b/crates/router/src/core/surcharge_decision_config.rs @@ -1,3 +1,13 @@ +use super::routing::helpers::{ + get_payment_method_surcharge_routing_id, update_merchant_active_algorithm_ref, +}; +use crate::{ + core::errors::{self, RouterResponse}, + routes::SessionState, + services::api as service_api, + types::domain, + utils::OptionExt, +}; use api_models::{ routing, surcharge_decision_configs::{ @@ -9,17 +19,7 @@ use common_utils::ext_traits::{Encode, StringExt, ValueExt}; use diesel_models::configs; use error_stack::ResultExt; use euclid::frontend::ast; - -use super::routing::helpers::{ - get_payment_method_surcharge_routing_id, update_merchant_active_algorithm_ref, -}; -use crate::{ - core::errors::{self, RouterResponse}, - routes::SessionState, - services::api as service_api, - types::domain, - utils::OptionExt, -}; +use storage_impl::redis::cache; pub async fn upsert_surcharge_decision_config( state: SessionState, @@ -89,7 +89,8 @@ pub async fn upsert_surcharge_decision_config( .attach_printable("Error serializing the config")?; algo_id.update_surcharge_config_id(key.clone()); - update_merchant_active_algorithm_ref(db, &key_store, &key, algo_id) + let config_key = cache::CacheKind::Surcharge(key.into()); + update_merchant_active_algorithm_ref(db, &key_store, config_key, algo_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update routing algorithm ref")?; @@ -125,7 +126,8 @@ pub async fn upsert_surcharge_decision_config( .attach_printable("Error fetching the config")?; algo_id.update_surcharge_config_id(key.clone()); - update_merchant_active_algorithm_ref(db, &key_store, &key, algo_id) + let config_key = cache::CacheKind::Surcharge(key.clone().into()); + update_merchant_active_algorithm_ref(db, &key_store, config_key, algo_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update routing algorithm ref")?; @@ -154,7 +156,8 @@ pub async fn delete_surcharge_decision_config( .attach_printable("Could not decode the surcharge conditional_config algorithm")? .unwrap_or_default(); algo_id.surcharge_config_algo_id = None; - update_merchant_active_algorithm_ref(db, &key_store, &key, algo_id) + let config_key = cache::CacheKind::Surcharge(key.clone().into()); + update_merchant_active_algorithm_ref(db, &key_store, config_key, algo_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update deleted algorithm ref")?; diff --git a/crates/storage_impl/src/redis/cache.rs b/crates/storage_impl/src/redis/cache.rs index d98eff44a89d..e4efab0da337 100644 --- a/crates/storage_impl/src/redis/cache.rs +++ b/crates/storage_impl/src/redis/cache.rs @@ -28,6 +28,12 @@ const ACCOUNTS_CACHE_PREFIX: &str = "accounts"; /// Prefix for routing cache key const ROUTING_CACHE_PREFIX: &str = "routing"; +/// Prefix for three ds decision manager cache key +const DECISION_MANAGER_CACHE_PREFIX: &str = "decision_manager"; + +/// Prefix for surcharge cache key +const SURCHARGE_CACHE_PREFIX: &str = "surcharge"; + /// Prefix for cgraph cache key const CGRAPH_CACHE_PREFIX: &str = "cgraph"; @@ -82,6 +88,8 @@ pub enum CacheKind<'a> { Config(Cow<'a, str>), Accounts(Cow<'a, str>), Routing(Cow<'a, str>), + DecisionManager(Cow<'a, str>), + Surcharge(Cow<'a, str>), CGraph(Cow<'a, str>), PmFiltersCGraph(Cow<'a, str>), All(Cow<'a, str>), @@ -93,6 +101,8 @@ impl<'a> From> for RedisValue { CacheKind::Config(s) => format!("{CONFIG_CACHE_PREFIX},{s}"), CacheKind::Accounts(s) => format!("{ACCOUNTS_CACHE_PREFIX},{s}"), CacheKind::Routing(s) => format!("{ROUTING_CACHE_PREFIX},{s}"), + CacheKind::DecisionManager(s) => format!("{DECISION_MANAGER_CACHE_PREFIX},{s}"), + CacheKind::Surcharge(s) => format!("{SURCHARGE_CACHE_PREFIX},{s}"), CacheKind::CGraph(s) => format!("{CGRAPH_CACHE_PREFIX},{s}"), CacheKind::PmFiltersCGraph(s) => format!("{PM_FILTERS_CGRAPH_CACHE_PREFIX},{s}"), CacheKind::All(s) => format!("{ALL_CACHE_PREFIX},{s}"), @@ -113,10 +123,15 @@ impl<'a> TryFrom for CacheKind<'a> { ACCOUNTS_CACHE_PREFIX => Ok(Self::Accounts(Cow::Owned(split.1.to_string()))), CONFIG_CACHE_PREFIX => Ok(Self::Config(Cow::Owned(split.1.to_string()))), ROUTING_CACHE_PREFIX => Ok(Self::Routing(Cow::Owned(split.1.to_string()))), + DECISION_MANAGER_CACHE_PREFIX => { + Ok(Self::DecisionManager(Cow::Owned(split.1.to_string()))) + } + SURCHARGE_CACHE_PREFIX => Ok(Self::Surcharge(Cow::Owned(split.1.to_string()))), CGRAPH_CACHE_PREFIX => Ok(Self::CGraph(Cow::Owned(split.1.to_string()))), PM_FILTERS_CGRAPH_CACHE_PREFIX => { Ok(Self::PmFiltersCGraph(Cow::Owned(split.1.to_string()))) } + ALL_CACHE_PREFIX => Ok(Self::All(Cow::Owned(split.1.to_string()))), _ => Err(validation_err.into()), } diff --git a/crates/storage_impl/src/redis/pub_sub.rs b/crates/storage_impl/src/redis/pub_sub.rs index e83546c0f8df..7c4bd93681f4 100644 --- a/crates/storage_impl/src/redis/pub_sub.rs +++ b/crates/storage_impl/src/redis/pub_sub.rs @@ -3,8 +3,8 @@ use redis_interface::{errors as redis_errors, PubsubInterface, RedisValue}; use router_env::{logger, tracing::Instrument}; use crate::redis::cache::{ - CacheKey, CacheKind, ACCOUNTS_CACHE, CGRAPH_CACHE, CONFIG_CACHE, PM_FILTERS_CGRAPH_CACHE, - ROUTING_CACHE, + CacheKey, CacheKind, ACCOUNTS_CACHE, CGRAPH_CACHE, CONFIG_CACHE, DECISION_MANAGER_CACHE, + PM_FILTERS_CGRAPH_CACHE, ROUTING_CACHE, SURCHARGE_CACHE, }; #[async_trait::async_trait] @@ -119,6 +119,24 @@ impl PubSubInterface for std::sync::Arc { .await; key } + CacheKind::DecisionManager(key) => { + DECISION_MANAGER_CACHE + .remove(CacheKey { + key: key.to_string(), + prefix: self.key_prefix.clone(), + }) + .await; + key + } + CacheKind::Surcharge(key) => { + SURCHARGE_CACHE + .remove(CacheKey { + key: key.to_string(), + prefix: self.key_prefix.clone(), + }) + .await; + key + } CacheKind::All(key) => { CONFIG_CACHE .remove(CacheKey { @@ -150,6 +168,19 @@ impl PubSubInterface for std::sync::Arc { prefix: self.key_prefix.clone(), }) .await; + DECISION_MANAGER_CACHE + .remove(CacheKey { + key: key.to_string(), + prefix: self.key_prefix.clone(), + }) + .await; + SURCHARGE_CACHE + .remove(CacheKey { + key: key.to_string(), + prefix: self.key_prefix.clone(), + }) + .await; + key } }; From dff5af413ee4e6ec3ce522a13bb380831d854772 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Fri, 7 Jun 2024 06:34:44 +0000 Subject: [PATCH 13/15] chore: run formatter --- crates/router/src/core/conditional_config.rs | 19 ++++++----- crates/router/src/core/routing.rs | 33 ++++++++++--------- .../src/core/surcharge_decision_config.rs | 21 ++++++------ 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/crates/router/src/core/conditional_config.rs b/crates/router/src/core/conditional_config.rs index 65b0eab70b3f..f740c6dfcc25 100644 --- a/crates/router/src/core/conditional_config.rs +++ b/crates/router/src/core/conditional_config.rs @@ -1,3 +1,13 @@ +use api_models::{ + conditional_configs::{DecisionManager, DecisionManagerRecord, DecisionManagerResponse}, + routing, +}; +use common_utils::ext_traits::{Encode, StringExt, ValueExt}; +use diesel_models::configs; +use error_stack::ResultExt; +use euclid::frontend::ast; +use storage_impl::redis::cache; + use super::routing::helpers::{ get_payment_config_routing_id, update_merchant_active_algorithm_ref, }; @@ -8,15 +18,6 @@ use crate::{ types::domain, utils::OptionExt, }; -use api_models::{ - conditional_configs::{DecisionManager, DecisionManagerRecord, DecisionManagerResponse}, - routing, -}; -use common_utils::ext_traits::{Encode, StringExt, ValueExt}; -use diesel_models::configs; -use error_stack::ResultExt; -use euclid::frontend::ast; -use storage_impl::redis::cache; pub async fn upsert_conditional_config( state: SessionState, diff --git a/crates/router/src/core/routing.rs b/crates/router/src/core/routing.rs index 766aeba6629c..c19e60dc3155 100644 --- a/crates/router/src/core/routing.rs +++ b/crates/router/src/core/routing.rs @@ -1,6 +1,23 @@ pub mod helpers; pub mod transformers; +#[cfg(feature = "business_profile_routing")] +use api_models::routing::{RoutingRetrieveLinkQuery, RoutingRetrieveQuery}; +use api_models::{ + enums, + routing::{self as routing_types, RoutingAlgorithmId}, +}; +#[cfg(not(feature = "business_profile_routing"))] +use common_utils::ext_traits::{Encode, StringExt}; +#[cfg(not(feature = "business_profile_routing"))] +use diesel_models::configs; +#[cfg(feature = "business_profile_routing")] +use diesel_models::routing_algorithm::RoutingAlgorithm; +use error_stack::ResultExt; +use rustc_hash::FxHashSet; +#[cfg(not(feature = "business_profile_routing"))] +use storage_impl::redis::cache; + use super::payments; #[cfg(feature = "payouts")] use super::payouts; @@ -20,22 +37,6 @@ use crate::{ use crate::{core::errors, services::api as service_api, types::storage}; #[cfg(feature = "business_profile_routing")] use crate::{errors, services::api as service_api}; -#[cfg(feature = "business_profile_routing")] -use api_models::routing::{RoutingRetrieveLinkQuery, RoutingRetrieveQuery}; -use api_models::{ - enums, - routing::{self as routing_types, RoutingAlgorithmId}, -}; -#[cfg(not(feature = "business_profile_routing"))] -use common_utils::ext_traits::{Encode, StringExt}; -#[cfg(not(feature = "business_profile_routing"))] -use diesel_models::configs; -#[cfg(feature = "business_profile_routing")] -use diesel_models::routing_algorithm::RoutingAlgorithm; -use error_stack::ResultExt; -use rustc_hash::FxHashSet; -#[cfg(not(feature = "business_profile_routing"))] -use storage_impl::redis::cache; pub enum TransactionData<'a, F> where diff --git a/crates/router/src/core/surcharge_decision_config.rs b/crates/router/src/core/surcharge_decision_config.rs index f3b39d85cdc1..b35d7c5ad285 100644 --- a/crates/router/src/core/surcharge_decision_config.rs +++ b/crates/router/src/core/surcharge_decision_config.rs @@ -1,13 +1,3 @@ -use super::routing::helpers::{ - get_payment_method_surcharge_routing_id, update_merchant_active_algorithm_ref, -}; -use crate::{ - core::errors::{self, RouterResponse}, - routes::SessionState, - services::api as service_api, - types::domain, - utils::OptionExt, -}; use api_models::{ routing, surcharge_decision_configs::{ @@ -21,6 +11,17 @@ use error_stack::ResultExt; use euclid::frontend::ast; use storage_impl::redis::cache; +use super::routing::helpers::{ + get_payment_method_surcharge_routing_id, update_merchant_active_algorithm_ref, +}; +use crate::{ + core::errors::{self, RouterResponse}, + routes::SessionState, + services::api as service_api, + types::domain, + utils::OptionExt, +}; + pub async fn upsert_surcharge_decision_config( state: SessionState, key_store: domain::MerchantKeyStore, From 28a9b50d7972512fa944c7e1193b968f74d2e611 Mon Sep 17 00:00:00 2001 From: Aprabhat19 Date: Fri, 7 Jun 2024 13:21:40 +0530 Subject: [PATCH 14/15] fix failing checks --- crates/router/src/core/routing.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/router/src/core/routing.rs b/crates/router/src/core/routing.rs index c19e60dc3155..2e95759e13c2 100644 --- a/crates/router/src/core/routing.rs +++ b/crates/router/src/core/routing.rs @@ -234,9 +234,10 @@ pub async fn create_routing_config( if records_are_empty { merchant_dictionary.active_id = Some(algorithm_id.clone()); algorithm_ref.update_algorithm_id(algorithm_id); - let key = cache::CacheKind::Routing(format!("dsl_{merchant_id}").into()); + let key = + cache::CacheKind::Routing(format!("dsl_{ &merchant_account.merchant_id}").into()); - helpers::update_merchant_active_algorithm_ref(db, &key_store, &key, algorithm_ref) + helpers::update_merchant_active_algorithm_ref(db, &key_store, key, algorithm_ref) .await?; } @@ -368,7 +369,7 @@ pub async fn link_routing_config( merchant_dictionary, ) .await?; - let key = cache::CacheKind::Routing(format!("dsl_{merchant_id}").into()); + let key = cache::CacheKind::Routing(format!("dsl_{ &merchant_account.merchant_id}").into()); helpers::update_merchant_active_algorithm_ref(db, &key_store, key, routing_ref).await?; metrics::ROUTING_LINK_CONFIG_SUCCESS_RESPONSE.add(&metrics::CONTEXT, 1, &[]); From 9a695c7ed1b5ad14ae0dc97fed65374c468803fb Mon Sep 17 00:00:00 2001 From: Aprabhat19 Date: Fri, 7 Jun 2024 16:09:03 +0530 Subject: [PATCH 15/15] fix failing checks --- crates/router/src/core/routing.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/router/src/core/routing.rs b/crates/router/src/core/routing.rs index 2e95759e13c2..5314de4d2f88 100644 --- a/crates/router/src/core/routing.rs +++ b/crates/router/src/core/routing.rs @@ -235,7 +235,7 @@ pub async fn create_routing_config( merchant_dictionary.active_id = Some(algorithm_id.clone()); algorithm_ref.update_algorithm_id(algorithm_id); let key = - cache::CacheKind::Routing(format!("dsl_{ &merchant_account.merchant_id}").into()); + cache::CacheKind::Routing(format!("dsl_{}", &merchant_account.merchant_id).into()); helpers::update_merchant_active_algorithm_ref(db, &key_store, key, algorithm_ref) .await?; @@ -369,7 +369,8 @@ pub async fn link_routing_config( merchant_dictionary, ) .await?; - let key = cache::CacheKind::Routing(format!("dsl_{ &merchant_account.merchant_id}").into()); + let key = + cache::CacheKind::Routing(format!("dsl_{}", &merchant_account.merchant_id).into()); helpers::update_merchant_active_algorithm_ref(db, &key_store, key, routing_ref).await?; metrics::ROUTING_LINK_CONFIG_SUCCESS_RESPONSE.add(&metrics::CONTEXT, 1, &[]);