@@ -96,14 +96,13 @@ def _evaluate_if_ready(self, matching_key, bucketing_key, feature, attributes=No
9696 }
9797 }
9898
99- return self ._evaluator .evaluate_treatment (
99+ return self ._evaluator .evaluate_feature (
100100 feature ,
101101 matching_key ,
102102 bucketing_key ,
103103 attributes
104104 )
105105
106-
107106 def get_treatment_with_config (self , key , feature , attributes = None ):
108107 """
109108 Get the treatment and config for a feature and key, with optional dictionary of attributes.
@@ -131,7 +130,7 @@ def get_treatment_with_config(self, key, feature, attributes=None):
131130 feature = input_validator .validate_feature_name (
132131 feature ,
133132 self .ready ,
134- self ._factory ._get_storage ('splits' ) #pylint: disable=protected-access
133+ self ._factory ._get_storage ('splits' ) # pylint: disable=protected-access
135134 )
136135
137136 if (matching_key is None and bucketing_key is None ) \
@@ -193,6 +192,24 @@ def get_treatment(self, key, feature, attributes=None):
193192 treatment , _ = self .get_treatment_with_config (key , feature , attributes )
194193 return treatment
195194
195+ def _evaluate_features_if_ready (self , matching_key , bucketing_key , features , attributes = None ):
196+ if not self .ready :
197+ return {
198+ feature : {
199+ 'treatment' : CONTROL ,
200+ 'configurations' : None ,
201+ 'impression' : {'label' : Label .NOT_READY , 'change_number' : None }
202+ }
203+ for feature in features
204+ }
205+
206+ return self ._evaluator .evaluate_features (
207+ features ,
208+ matching_key ,
209+ bucketing_key ,
210+ attributes
211+ )
212+
196213 def get_treatments_with_config (self , key , features , attributes = None ):
197214 """
198215 Evaluate multiple features and return a dict with feature -> (treatment, config).
@@ -233,39 +250,47 @@ def get_treatments_with_config(self, key, features, attributes=None):
233250 bulk_impressions = []
234251 treatments = {name : (CONTROL , None ) for name in missing }
235252
236- for feature in features :
253+ try :
254+ evaluations = self ._evaluate_features_if_ready (matching_key , bucketing_key ,
255+ list (features ), attributes )
256+
257+ for feature in features :
258+ try :
259+ result = evaluations [feature ]
260+ impression = self ._build_impression (matching_key ,
261+ feature ,
262+ result ['treatment' ],
263+ result ['impression' ]['label' ],
264+ result ['impression' ]['change_number' ],
265+ bucketing_key ,
266+ start )
267+
268+ bulk_impressions .append (impression )
269+ treatments [feature ] = (result ['treatment' ], result ['configurations' ])
270+
271+ except Exception : # pylint: disable=broad-except
272+ self ._logger .error ('get_treatments: An exception occured when evaluating '
273+ 'feature ' + feature + ' returning CONTROL.' )
274+ treatments [feature ] = CONTROL , None
275+ self ._logger .debug ('Error: ' , exc_info = True )
276+ continue
277+
278+ # Register impressions
237279 try :
238- result = self ._evaluate_if_ready (matching_key , bucketing_key , feature , attributes )
239- impression = self ._build_impression (matching_key ,
240- feature ,
241- result ['treatment' ],
242- result ['impression' ]['label' ],
243- result ['impression' ]['change_number' ],
244- bucketing_key ,
245- start )
246-
247- bulk_impressions .append (impression )
248- treatments [feature ] = (result ['treatment' ], result ['configurations' ])
249-
280+ if bulk_impressions :
281+ self ._record_stats (bulk_impressions , start , self ._METRIC_GET_TREATMENTS )
282+ for impression in bulk_impressions :
283+ self ._send_impression_to_listener (impression , attributes )
250284 except Exception : # pylint: disable=broad-except
251- self ._logger .error ('get_treatments: An exception occured when evaluating '
252- 'feature ' + feature + ' returning CONTROL.' )
253- treatments [feature ] = CONTROL , None
285+ self ._logger .error ('get_treatments: An exception when trying to store '
286+ 'impressions.' )
254287 self ._logger .debug ('Error: ' , exc_info = True )
255- continue
256288
257- # Register impressions
258- try :
259- if bulk_impressions :
260- self ._record_stats (bulk_impressions , start , self ._METRIC_GET_TREATMENTS )
261- for impression in bulk_impressions :
262- self ._send_impression_to_listener (impression , attributes )
289+ return treatments
263290 except Exception : # pylint: disable=broad-except
264- self ._logger .error ('get_treatments: An exception when trying to store '
265- 'impressions.' )
291+ self ._logger .error ('Error getting treatment for features' )
266292 self ._logger .debug ('Error: ' , exc_info = True )
267-
268- return treatments
293+ return input_validator .generate_control_treatments (list (features ))
269294
270295 def get_treatments (self , key , features , attributes = None ):
271296 """
@@ -354,11 +379,11 @@ def track(self, key, traffic_type, event_type, value=None, properties=None):
354379
355380 key = input_validator .validate_track_key (key )
356381 event_type = input_validator .validate_event_type (event_type )
357- should_validate_existance = self .ready and self ._factory ._apikey != 'localhost' # pylint: disable=protected-access
382+ should_validate_existance = self .ready and self ._factory ._apikey != 'localhost' # pylint: disable=protected-access
358383 traffic_type = input_validator .validate_traffic_type (
359384 traffic_type ,
360385 should_validate_existance ,
361- self ._factory ._get_storage ('splits' ), # pylint: disable=protected-access
386+ self ._factory ._get_storage ('splits' ), # pylint: disable=protected-access
362387 )
363388
364389 value = input_validator .validate_value (value )
0 commit comments