1
- use std:: sync:: Arc ;
2
-
3
1
use api_models:: {
4
2
payment_methods:: SurchargeDetailsResponse ,
5
3
payments, routing,
6
4
surcharge_decision_configs:: { self , SurchargeDecisionConfigs , SurchargeDecisionManagerRecord } ,
7
5
} ;
8
- use common_utils:: { ext_traits:: StringExt , static_cache :: StaticCache , types as common_utils_types} ;
6
+ use common_utils:: { ext_traits:: StringExt , types as common_utils_types} ;
9
7
use error_stack:: { self , ResultExt } ;
10
8
use euclid:: {
11
9
backend,
12
10
backend:: { inputs as dsl_inputs, EuclidBackend } ,
13
11
} ;
14
12
use router_env:: { instrument, tracing} ;
13
+ use serde:: { Deserialize , Serialize } ;
14
+ use storage_impl:: redis:: cache:: { self , SURCHARGE_CACHE } ;
15
15
16
16
use crate :: {
17
17
core:: {
18
- errors:: ConditionalConfigError as ConfigError ,
18
+ errors:: { self , ConditionalConfigError as ConfigError } ,
19
19
payments:: {
20
20
conditional_configs:: ConditionalConfigResult , routing:: make_dsl_input_for_surcharge,
21
21
types, PaymentData ,
@@ -29,9 +29,8 @@ use crate::{
29
29
SessionState ,
30
30
} ;
31
31
32
- static CONF_CACHE : StaticCache < VirInterpreterBackendCacheWrapper > = StaticCache :: new ( ) ;
33
-
34
- struct VirInterpreterBackendCacheWrapper {
32
+ #[ derive( Debug , Serialize , Deserialize , Clone ) ]
33
+ pub struct VirInterpreterBackendCacheWrapper {
35
34
cached_algorithm : backend:: VirInterpreterBackend < SurchargeDecisionConfigs > ,
36
35
merchant_surcharge_configs : surcharge_decision_configs:: MerchantSurchargeConfigs ,
37
36
}
@@ -53,7 +52,7 @@ impl TryFrom<SurchargeDecisionManagerRecord> for VirInterpreterBackendCacheWrapp
53
52
54
53
enum SurchargeSource {
55
54
/// Surcharge will be generated through the surcharge rules
56
- Generate ( Arc < VirInterpreterBackendCacheWrapper > ) ,
55
+ Generate ( VirInterpreterBackendCacheWrapper ) ,
57
56
/// Surcharge is predefined by the merchant through payment create request
58
57
Predetermined ( payments:: RequestSurchargeDetails ) ,
59
58
}
@@ -116,19 +115,13 @@ pub async fn perform_surcharge_decision_management_for_payment_method_list(
116
115
surcharge_decision_configs:: MerchantSurchargeConfigs :: default ( ) ,
117
116
) ,
118
117
( None , Some ( algorithm_id) ) => {
119
- let key = ensure_algorithm_cached (
118
+ let cached_algo = ensure_algorithm_cached (
120
119
& * state. store ,
121
120
& payment_attempt. merchant_id ,
122
- algorithm_ref. timestamp ,
123
121
algorithm_id. as_str ( ) ,
124
122
)
125
123
. await ?;
126
- let cached_algo = CONF_CACHE
127
- . retrieve ( & key)
128
- . change_context ( ConfigError :: CacheMiss )
129
- . attach_printable (
130
- "Unable to retrieve cached routing algorithm even after refresh" ,
131
- ) ?;
124
+
132
125
let merchant_surcharge_config = cached_algo. merchant_surcharge_configs . clone ( ) ;
133
126
(
134
127
SurchargeSource :: Generate ( cached_algo) ,
@@ -233,19 +226,13 @@ where
233
226
SurchargeSource :: Predetermined ( request_surcharge_details)
234
227
}
235
228
( None , Some ( algorithm_id) ) => {
236
- let key = ensure_algorithm_cached (
229
+ let cached_algo = ensure_algorithm_cached (
237
230
& * state. store ,
238
231
& payment_data. payment_attempt . merchant_id ,
239
- algorithm_ref. timestamp ,
240
232
algorithm_id. as_str ( ) ,
241
233
)
242
234
. await ?;
243
- let cached_algo = CONF_CACHE
244
- . retrieve ( & key)
245
- . change_context ( ConfigError :: CacheMiss )
246
- . attach_printable (
247
- "Unable to retrieve cached routing algorithm even after refresh" ,
248
- ) ?;
235
+
249
236
SurchargeSource :: Generate ( cached_algo)
250
237
}
251
238
( None , None ) => return Ok ( surcharge_metadata) ,
@@ -291,19 +278,13 @@ pub async fn perform_surcharge_decision_management_for_saved_cards(
291
278
SurchargeSource :: Predetermined ( request_surcharge_details)
292
279
}
293
280
( None , Some ( algorithm_id) ) => {
294
- let key = ensure_algorithm_cached (
281
+ let cached_algo = ensure_algorithm_cached (
295
282
& * state. store ,
296
283
& payment_attempt. merchant_id ,
297
- algorithm_ref. timestamp ,
298
284
algorithm_id. as_str ( ) ,
299
285
)
300
286
. await ?;
301
- let cached_algo = CONF_CACHE
302
- . retrieve ( & key)
303
- . change_context ( ConfigError :: CacheMiss )
304
- . attach_printable (
305
- "Unable to retrieve cached routing algorithm even after refresh" ,
306
- ) ?;
287
+
307
288
SurchargeSource :: Generate ( cached_algo)
308
289
}
309
290
( None , None ) => return Ok ( surcharge_metadata) ,
@@ -388,48 +369,31 @@ fn get_surcharge_details_from_surcharge_output(
388
369
pub async fn ensure_algorithm_cached (
389
370
store : & dyn StorageInterface ,
390
371
merchant_id : & str ,
391
- timestamp : i64 ,
392
372
algorithm_id : & str ,
393
- ) -> ConditionalConfigResult < String > {
373
+ ) -> ConditionalConfigResult < VirInterpreterBackendCacheWrapper > {
394
374
let key = format ! ( "surcharge_dsl_{merchant_id}" ) ;
395
- let present = CONF_CACHE
396
- . present ( & key)
397
- . change_context ( ConfigError :: DslCachePoisoned )
398
- . attach_printable ( "Error checking presence of DSL" ) ?;
399
- let expired = CONF_CACHE
400
- . expired ( & key, timestamp)
401
- . change_context ( ConfigError :: DslCachePoisoned )
402
- . attach_printable ( "Error checking presence of DSL" ) ?;
403
375
404
- if !present || expired {
405
- refresh_surcharge_algorithm_cache ( store, key. clone ( ) , algorithm_id, timestamp) . await ?
406
- }
407
- Ok ( key)
408
- }
409
-
410
- #[ instrument( skip_all) ]
411
- pub async fn refresh_surcharge_algorithm_cache (
412
- store : & dyn StorageInterface ,
413
- key : String ,
414
- algorithm_id : & str ,
415
- timestamp : i64 ,
416
- ) -> ConditionalConfigResult < ( ) > {
417
- let config = store
418
- . find_config_by_key ( algorithm_id)
419
- . await
420
- . change_context ( ConfigError :: DslMissingInDb )
421
- . attach_printable ( "Error parsing DSL from config" ) ?;
422
- let record: SurchargeDecisionManagerRecord = config
423
- . config
424
- . parse_struct ( "Program" )
425
- . change_context ( ConfigError :: DslParsingError )
426
- . attach_printable ( "Error parsing routing algorithm from configs" ) ?;
427
- let value_to_cache = VirInterpreterBackendCacheWrapper :: try_from ( record) ?;
428
- CONF_CACHE
429
- . save ( key, value_to_cache, timestamp)
430
- . change_context ( ConfigError :: DslCachePoisoned )
431
- . attach_printable ( "Error saving DSL to cache" ) ?;
432
- Ok ( ( ) )
376
+ let value_to_cache = || async {
377
+ let config: diesel_models:: Config = store. find_config_by_key ( algorithm_id) . await ?;
378
+ let record: SurchargeDecisionManagerRecord = config
379
+ . config
380
+ . parse_struct ( "Program" )
381
+ . change_context ( errors:: StorageError :: DeserializationFailed )
382
+ . attach_printable ( "Error parsing routing algorithm from configs" ) ?;
383
+ VirInterpreterBackendCacheWrapper :: try_from ( record)
384
+ . change_context ( errors:: StorageError :: ValueNotFound ( "Program" . to_string ( ) ) )
385
+ . attach_printable ( "Error initializing DSL interpreter backend" )
386
+ } ;
387
+ let interpreter = cache:: get_or_populate_in_memory (
388
+ store. get_cache_store ( ) . as_ref ( ) ,
389
+ & key,
390
+ value_to_cache,
391
+ & SURCHARGE_CACHE ,
392
+ )
393
+ . await
394
+ . change_context ( ConfigError :: CacheMiss )
395
+ . attach_printable ( "Unable to retrieve cached routing algorithm even after refresh" ) ?;
396
+ Ok ( interpreter)
433
397
}
434
398
435
399
pub fn execute_dsl_and_get_conditional_config (
0 commit comments