Skip to content

Commit d7b06a0

Browse files
committed
Added old spec for Localhost
1 parent 9aa56a1 commit d7b06a0

File tree

15 files changed

+206
-71
lines changed

15 files changed

+206
-71
lines changed

splitio/api/splits.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from splitio.models.telemetry import HTTPExceptionsAndLatencies
1010
from splitio.util.time import utctime_ms
1111
from splitio.spec import SPEC_VERSION
12+
from splitio.sync import util
1213

1314
_LOGGER = logging.getLogger(__name__)
1415
_SPEC_1_1 = "1.1"
@@ -37,10 +38,6 @@ def __init__(self, client, sdk_key, sdk_metadata, telemetry_runtime_producer):
3738
self._last_proxy_check_timestamp = 0
3839
self.clear_storage = False
3940

40-
def _convert_to_new_spec(self, body):
41-
return {"ff": {"d": body["splits"], "s": body["since"], "t": body["till"]},
42-
"rbs": {"d": [], "s": -1, "t": -1}}
43-
4441
def _check_last_proxy_check_timestamp(self):
4542
if self._spec_version == _SPEC_1_1 and ((utctime_ms() - self._last_proxy_check_timestamp) >= _PROXY_CHECK_INTERVAL_MILLISECONDS_SS):
4643
_LOGGER.info("Switching to new Feature flag spec (%s) and fetching.", SPEC_VERSION);
@@ -91,7 +88,7 @@ def fetch_splits(self, change_number, rbs_change_number, fetch_options):
9188
)
9289
if 200 <= response.status_code < 300:
9390
if self._spec_version == _SPEC_1_1:
94-
return self._convert_to_new_spec(json.loads(response.body))
91+
return util.convert_to_new_spec(json.loads(response.body))
9592

9693
self.clear_storage = self._last_proxy_check_timestamp != 0
9794
self._last_proxy_check_timestamp = 0
@@ -159,7 +156,7 @@ async def fetch_splits(self, change_number, rbs_change_number, fetch_options):
159156
)
160157
if 200 <= response.status_code < 300:
161158
if self._spec_version == _SPEC_1_1:
162-
return self._convert_to_new_spec(json.loads(response.body))
159+
return util.convert_to_new_spec(json.loads(response.body))
163160

164161
self.clear_storage = self._last_proxy_check_timestamp != 0
165162
self._last_proxy_check_timestamp = 0

splitio/engine/evaluator.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
from splitio.models.grammar.condition import ConditionType
77
from splitio.models.grammar.matchers.misc import DependencyMatcher
88
from 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
1011
from splitio.optional.loaders import asyncio
1112

1213
CONTROL = 'control'
13-
EvaluationContext = namedtuple('EvaluationContext', ['flags', 'segment_memberships', 'segment_rbs_memberships', 'segment_rbs_conditions'])
14+
EvaluationContext = namedtuple('EvaluationContext', ['flags', 'segment_memberships', 'segment_rbs_memberships', 'segment_rbs_conditions', 'excluded_rbs_segments'])
1415

1516
_LOGGER = logging.getLogger(__name__)
1617

@@ -130,6 +131,7 @@ def context_for(self, key, feature_names):
130131

131132
rbs_segment_memberships = {}
132133
rbs_segment_conditions = {}
134+
excluded_rbs_segments = {}
133135
key_membership = False
134136
segment_memberhsip = False
135137
for rbs_segment in pending_rbs_memberships:
@@ -138,10 +140,14 @@ def context_for(self, key, feature_names):
138140

139141
key_membership = key in rbs_segment_obj.excluded.get_excluded_keys()
140142
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+
for excluded_segment in rbs_segment_obj.excluded.get_excluded_segments():
144+
if excluded_segment.type == SegmentType.STANDARD and self._segment_storage.segment_contains(excluded_segment.name, key):
143145
segment_memberhsip = True
144-
break
146+
147+
if excluded_segment.type == SegmentType.RULE_BASED:
148+
rbs_segment = self._rbs_segment_storage.get(excluded_segment.name)
149+
if rbs_segment is not None:
150+
excluded_rbs_segments.update()
145151

146152
rbs_segment_memberships.update({rbs_segment: segment_memberhsip or key_membership})
147153
if not (segment_memberhsip or key_membership):
@@ -153,7 +159,8 @@ def context_for(self, key, feature_names):
153159
for segment in pending_memberships
154160
},
155161
rbs_segment_memberships,
156-
rbs_segment_conditions
162+
rbs_segment_conditions,
163+
excluded_rbs_segments
157164
)
158165

159166
class AsyncEvaluationDataFactory:
@@ -189,6 +196,7 @@ async def context_for(self, key, feature_names):
189196

190197
rbs_segment_memberships = {}
191198
rbs_segment_conditions = {}
199+
excluded_rbs_segments = {}
192200
key_membership = False
193201
segment_memberhsip = False
194202
for rbs_segment in pending_rbs_memberships:
@@ -197,11 +205,15 @@ async def context_for(self, key, feature_names):
197205

198206
key_membership = key in rbs_segment_obj.excluded.get_excluded_keys()
199207
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):
208+
for excluded_segment in rbs_segment_obj.excluded.get_excluded_segments():
209+
if excluded_segment.type == SegmentType.STANDARD and await self._segment_storage.segment_contains(excluded_segment.name, key):
202210
segment_memberhsip = True
203-
break
204-
211+
212+
if excluded_segment.type == SegmentType.RULE_BASED:
213+
rbs_segment = await self._rbs_segment_storage.get(excluded_segment.name)
214+
if rbs_segment is not None:
215+
excluded_rbs_segments.update()
216+
205217
rbs_segment_memberships.update({rbs_segment: segment_memberhsip or key_membership})
206218
if not (segment_memberhsip or key_membership):
207219
rbs_segment_conditions.update({rbs_segment: [condition for condition in rbs_segment_obj.conditions]})
@@ -215,7 +227,8 @@ async def context_for(self, key, feature_names):
215227
splits,
216228
dict(zip(segment_names, segment_memberships)),
217229
rbs_segment_memberships,
218-
rbs_segment_conditions
230+
rbs_segment_conditions,
231+
excluded_rbs_segments
219232
)
220233

221234

splitio/models/grammar/matchers/rule_based_segment.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,14 @@ def _match(self, key, attributes=None, context=None):
3232
# Check if rbs segment has exclusions
3333
if context['ec'].segment_rbs_memberships.get(self._rbs_segment_name):
3434
return False
35-
36-
for parsed_condition in context['ec'].segment_rbs_conditions.get(self._rbs_segment_name):
37-
if parsed_condition.matches(key, attributes, context):
35+
36+
for rbs_segment in context['ec'].excluded_rbs_segments:
37+
if self._match_conditions(rbs_segment, key, attributes, context):
3838
return True
39-
39+
40+
if self._match_conditions(context['ec'].segment_rbs_conditions.get(self._rbs_segment_name), key, attributes, context):
41+
return True
42+
4043
return False
4144

4245
def _add_matcher_specific_properties_to_json(self):
@@ -45,4 +48,9 @@ def _add_matcher_specific_properties_to_json(self):
4548
'userDefinedSegmentMatcherData': {
4649
'segmentName': self._rbs_segment_name
4750
}
48-
}
51+
}
52+
53+
def _match_conditions(self, rbs_segment, key, attributes, context):
54+
for parsed_condition in rbs_segment:
55+
if parsed_condition.matches(key, attributes, context):
56+
return True

splitio/models/rule_based_segments.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""RuleBasedSegment module."""
22

3+
from enum import Enum
34
import logging
45

56
from splitio.models import MatcherNotFoundException
@@ -9,6 +10,12 @@
910

1011
_LOGGER = logging.getLogger(__name__)
1112

13+
class SegmentType(Enum):
14+
"""Segment type."""
15+
16+
STANDARD = "standard"
17+
RULE_BASED = "rule-based"
18+
1219
class RuleBasedSegment(object):
1320
"""RuleBasedSegment object class."""
1421

@@ -125,7 +132,7 @@ def __init__(self, keys, segments):
125132
:type segments: List
126133
"""
127134
self._keys = keys
128-
self._segments = segments
135+
self._segments = [ExcludedSegment(segment['name'], segment['type']) for segment in segments]
129136

130137
def get_excluded_keys(self):
131138
"""Return excluded keys."""
@@ -141,3 +148,30 @@ def to_json(self):
141148
'keys': self._keys,
142149
'segments': self._segments
143150
}
151+
152+
class ExcludedSegment(object):
153+
154+
def __init__(self, name, type):
155+
"""
156+
Class constructor.
157+
158+
:param name: rule based segment name
159+
:type name: str
160+
:param type: segment type
161+
:type type: str
162+
"""
163+
self._name = name
164+
try:
165+
self._type = SegmentType(type)
166+
except ValueError:
167+
self._type = SegmentType.STANDARD
168+
169+
@property
170+
def name(self):
171+
"""Return name."""
172+
return self._name
173+
174+
@property
175+
def type(self):
176+
"""Return type."""
177+
return self._type

splitio/storage/inmemmory.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ async def clear(self):
243243
"""
244244
Clear storage
245245
"""
246-
with self._lock:
246+
async with self._lock:
247247
self._rule_based_segments = {}
248248
self._change_number = -1
249249

@@ -702,7 +702,7 @@ async def clear(self):
702702
"""
703703
Clear storage
704704
"""
705-
with self._lock:
705+
async with self._lock:
706706
self._feature_flags = {}
707707
self._change_number = -1
708708
self._traffic_types = Counter()

0 commit comments

Comments
 (0)