1515import hashlib
1616import threading
1717
18- from typing import Optional , List , TypedDict
18+ from typing import Optional , List , TypedDict , Tuple
1919from optimizely .cmab .cmab_client import DefaultCmabClient
2020from optimizely .odp .lru_cache import LRUCache
2121from optimizely .optimizely_user_context import OptimizelyUserContext , UserAttributes
@@ -65,26 +65,40 @@ def _get_lock_index(self, user_id: str, rule_id: str) -> int:
6565 return hash_value % NUM_LOCK_STRIPES
6666
6767 def get_decision (self , project_config : ProjectConfig , user_context : OptimizelyUserContext ,
68- rule_id : str , options : List [str ]) -> CmabDecision :
68+ rule_id : str , options : List [str ]) -> Tuple [ CmabDecision , List [ str ]] :
6969
7070 lock_index = self ._get_lock_index (user_context .user_id , rule_id )
7171 with self .locks [lock_index ]:
7272 return self ._get_decision (project_config , user_context , rule_id , options )
7373
7474 def _get_decision (self , project_config : ProjectConfig , user_context : OptimizelyUserContext ,
75- rule_id : str , options : List [str ]) -> CmabDecision :
75+ rule_id : str , options : List [str ]) -> Tuple [ CmabDecision , List [ str ]] :
7676
7777 filtered_attributes = self ._filter_attributes (project_config , user_context , rule_id )
78+ reasons = []
7879
7980 if OptimizelyDecideOption .IGNORE_CMAB_CACHE in options :
80- return self ._fetch_decision (rule_id , user_context .user_id , filtered_attributes )
81+ reason = f"Ignoring CMAB cache for user '{ user_context .user_id } ' and rule '{ rule_id } '"
82+ if self .logger :
83+ self .logger .debug (reason )
84+ reasons .append (reason )
85+ cmab_decision = self ._fetch_decision (rule_id , user_context .user_id , filtered_attributes )
86+ return cmab_decision , reasons
8187
8288 if OptimizelyDecideOption .RESET_CMAB_CACHE in options :
89+ reason = f"Resetting CMAB cache for user '{ user_context .user_id } ' and rule '{ rule_id } '"
90+ if self .logger :
91+ self .logger .debug (reason )
92+ reasons .append (reason )
8393 self .cmab_cache .reset ()
8494
8595 cache_key = self ._get_cache_key (user_context .user_id , rule_id )
8696
8797 if OptimizelyDecideOption .INVALIDATE_USER_CMAB_CACHE in options :
98+ reason = f"Invalidating CMAB cache for user '{ user_context .user_id } ' and rule '{ rule_id } '"
99+ if self .logger :
100+ self .logger .debug (reason )
101+ reasons .append (reason )
88102 self .cmab_cache .remove (cache_key )
89103
90104 cached_value = self .cmab_cache .lookup (cache_key )
@@ -93,17 +107,35 @@ def _get_decision(self, project_config: ProjectConfig, user_context: OptimizelyU
93107
94108 if cached_value :
95109 if cached_value ['attributes_hash' ] == attributes_hash :
96- return CmabDecision (variation_id = cached_value ['variation_id' ], cmab_uuid = cached_value ['cmab_uuid' ])
110+ reason = f"CMAB cache hit for user '{ user_context .user_id } ' and rule '{ rule_id } '"
111+ if self .logger :
112+ self .logger .debug (reason )
113+ reasons .append (reason )
114+ return CmabDecision (variation_id = cached_value ['variation_id' ], cmab_uuid = cached_value ['cmab_uuid' ]), reasons
97115 else :
116+ reason = f"CMAB cache attributes mismatch for user '{ user_context .user_id } ' and rule '{ rule_id } ', fetching new decision."
117+ if self .logger :
118+ self .logger .debug (reason )
119+ reasons .append (reason )
98120 self .cmab_cache .remove (cache_key )
121+ else :
122+ reason = f"CMAB cache miss for user '{ user_context .user_id } ' and rule '{ rule_id } '"
123+ if self .logger :
124+ self .logger .debug (reason )
125+ reasons .append (reason )
99126
100127 cmab_decision = self ._fetch_decision (rule_id , user_context .user_id , filtered_attributes )
128+ reason = f"CMAB decision is { cmab_decision } "
129+ if self .logger :
130+ self .logger .debug (reason )
131+ reasons .append (reason )
132+
101133 self .cmab_cache .save (cache_key , {
102134 'attributes_hash' : attributes_hash ,
103135 'variation_id' : cmab_decision ['variation_id' ],
104136 'cmab_uuid' : cmab_decision ['cmab_uuid' ],
105137 })
106- return cmab_decision
138+ return cmab_decision , reasons
107139
108140 def _fetch_decision (self , rule_id : str , user_id : str , attributes : UserAttributes ) -> CmabDecision :
109141 cmab_uuid = str (uuid .uuid4 ())
0 commit comments