66from splitio .models .grammar .condition import ConditionType
77from splitio .models .grammar .matchers .misc import DependencyMatcher
88from splitio .models .grammar .matchers .keys import UserDefinedSegmentMatcher
9- from splitio .models .grammar .matchers .rule_based_segment import RuleBasedSegmentMatcher
9+ from splitio .models .grammar .matchers import RuleBasedSegmentMatcher
10+ from splitio .models .rule_based_segments import SegmentType
1011from splitio .optional .loaders import asyncio
1112
1213CONTROL = 'control'
13- EvaluationContext = namedtuple ('EvaluationContext' , ['flags' , 'segment_memberships' , 'segment_rbs_memberships' , 'segment_rbs_conditions ' ])
14+ EvaluationContext = namedtuple ('EvaluationContext' , ['flags' , 'segment_memberships' , 'rbs_segments ' ])
1415
1516_LOGGER = logging .getLogger (__name__ )
1617
@@ -114,47 +115,24 @@ def context_for(self, key, feature_names):
114115 :rtype: EvaluationContext
115116 """
116117 pending = set (feature_names )
118+ pending_rbs = set ()
117119 splits = {}
120+ rb_segments = {}
118121 pending_memberships = set ()
119- pending_rbs_memberships = set ()
120- while pending :
122+ while pending or pending_rbs :
121123 fetched = self ._flag_storage .fetch_many (list (pending ))
122- features = filter_missing (fetched )
123- splits .update (features )
124- pending = set ()
125- for feature in features .values ():
126- cf , cs , crbs = get_dependencies (feature )
127- pending .update (filter (lambda f : f not in splits , cf ))
128- pending_memberships .update (cs )
129- pending_rbs_memberships .update (crbs )
130-
131- rbs_segment_memberships = {}
132- rbs_segment_conditions = {}
133- key_membership = False
134- segment_memberhsip = False
135- for rbs_segment in pending_rbs_memberships :
136- rbs_segment_obj = self ._rbs_segment_storage .get (rbs_segment )
137- pending_memberships .update (rbs_segment_obj .get_condition_segment_names ())
138-
139- key_membership = key in rbs_segment_obj .excluded .get_excluded_keys ()
140- segment_memberhsip = False
141- for segment_name in rbs_segment_obj .excluded .get_excluded_segments ():
142- if self ._segment_storage .segment_contains (segment_name , key ):
143- segment_memberhsip = True
144- break
145-
146- rbs_segment_memberships .update ({rbs_segment : segment_memberhsip or key_membership })
147- if not (segment_memberhsip or key_membership ):
148- rbs_segment_conditions .update ({rbs_segment : [condition for condition in rbs_segment_obj .conditions ]})
149-
124+ fetched_rbs = self ._rbs_segment_storage .fetch_many (list (pending_rbs ))
125+ features , rbsegments , splits , rb_segments = update_objects (fetched , fetched_rbs , splits , rb_segments )
126+ pending , pending_memberships , pending_rbs = get_pending_objects (features , splits , rbsegments , rb_segments , pending_memberships )
127+
150128 return EvaluationContext (
151129 splits ,
152130 { segment : self ._segment_storage .segment_contains (segment , key )
153131 for segment in pending_memberships
154132 },
155- rbs_segment_memberships ,
156- rbs_segment_conditions
133+ rb_segments
157134 )
135+
158136
159137class AsyncEvaluationDataFactory :
160138
@@ -173,60 +151,36 @@ async def context_for(self, key, feature_names):
173151 :rtype: EvaluationContext
174152 """
175153 pending = set (feature_names )
154+ pending_rbs = set ()
176155 splits = {}
156+ rb_segments = {}
177157 pending_memberships = set ()
178- pending_rbs_memberships = set ()
179- while pending :
158+ while pending or pending_rbs :
180159 fetched = await self ._flag_storage .fetch_many (list (pending ))
181- features = filter_missing (fetched )
182- splits .update (features )
183- pending = set ()
184- for feature in features .values ():
185- cf , cs , crbs = get_dependencies (feature )
186- pending .update (filter (lambda f : f not in splits , cf ))
187- pending_memberships .update (cs )
188- pending_rbs_memberships .update (crbs )
189-
190- rbs_segment_memberships = {}
191- rbs_segment_conditions = {}
192- key_membership = False
193- segment_memberhsip = False
194- for rbs_segment in pending_rbs_memberships :
195- rbs_segment_obj = await self ._rbs_segment_storage .get (rbs_segment )
196- pending_memberships .update (rbs_segment_obj .get_condition_segment_names ())
197-
198- key_membership = key in rbs_segment_obj .excluded .get_excluded_keys ()
199- segment_memberhsip = False
200- for segment_name in rbs_segment_obj .excluded .get_excluded_segments ():
201- if await self ._segment_storage .segment_contains (segment_name , key ):
202- segment_memberhsip = True
203- break
204-
205- rbs_segment_memberships .update ({rbs_segment : segment_memberhsip or key_membership })
206- if not (segment_memberhsip or key_membership ):
207- rbs_segment_conditions .update ({rbs_segment : [condition for condition in rbs_segment_obj .conditions ]})
160+ fetched_rbs = await self ._rbs_segment_storage .fetch_many (list (pending_rbs ))
161+ features , rbsegments , splits , rb_segments = update_objects (fetched , fetched_rbs , splits , rb_segments )
162+ pending , pending_memberships , pending_rbs = get_pending_objects (features , splits , rbsegments , rb_segments , pending_memberships )
208163
209164 segment_names = list (pending_memberships )
210165 segment_memberships = await asyncio .gather (* [
211166 self ._segment_storage .segment_contains (segment , key )
212167 for segment in segment_names
213168 ])
169+
214170 return EvaluationContext (
215171 splits ,
216172 dict (zip (segment_names , segment_memberships )),
217- rbs_segment_memberships ,
218- rbs_segment_conditions
173+ rb_segments
219174 )
220175
221-
222- def get_dependencies (feature ):
176+ def get_dependencies (object ):
223177 """
224178 :rtype: tuple(list, list)
225179 """
226180 feature_names = []
227181 segment_names = []
228182 rbs_segment_names = []
229- for condition in feature .conditions :
183+ for condition in object .conditions :
230184 for matcher in condition .matchers :
231185 if isinstance (matcher ,RuleBasedSegmentMatcher ):
232186 rbs_segment_names .append (matcher ._rbs_segment_name )
@@ -239,3 +193,34 @@ def get_dependencies(feature):
239193
240194def filter_missing (features ):
241195 return {k : v for (k , v ) in features .items () if v is not None }
196+
197+ def get_pending_objects (features , splits , rbsegments , rb_segments , pending_memberships ):
198+ pending = set ()
199+ pending_rbs = set ()
200+ for feature in features .values ():
201+ cf , cs , crbs = get_dependencies (feature )
202+ pending .update (filter (lambda f : f not in splits , cf ))
203+ pending_memberships .update (cs )
204+ pending_rbs .update (filter (lambda f : f not in rb_segments , crbs ))
205+
206+ for rb_segment in rbsegments .values ():
207+ cf , cs , crbs = get_dependencies (rb_segment )
208+ pending .update (filter (lambda f : f not in splits , cf ))
209+ pending_memberships .update (cs )
210+ for excluded_segment in rb_segment .excluded .get_excluded_segments ():
211+ if excluded_segment .type == SegmentType .STANDARD :
212+ pending_memberships .add (excluded_segment .name )
213+ else :
214+ pending_rbs .update (filter (lambda f : f not in rb_segments , [excluded_segment .name ]))
215+ pending_rbs .update (filter (lambda f : f not in rb_segments , crbs ))
216+
217+ return pending , pending_memberships , pending_rbs
218+
219+ def update_objects (fetched , fetched_rbs , splits , rb_segments ):
220+ features = filter_missing (fetched )
221+ rbsegments = filter_missing (fetched_rbs )
222+ splits .update (features )
223+ rb_segments .update (rbsegments )
224+
225+ return features , rbsegments , splits , rb_segments
226+
0 commit comments