Skip to content

Commit 9e94dcd

Browse files
committed
added flagset and flagsetfilter classes and updated other classes
1 parent a5a872e commit 9e94dcd

File tree

12 files changed

+1051
-1169
lines changed

12 files changed

+1051
-1169
lines changed

splitio/client/client.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,11 @@ def _get_feature_flag_names_by_flag_sets(self, flag_sets):
429429
:rtype: list
430430
"""
431431
sanitized_flag_sets = config.sanitize_flag_sets(flag_sets)
432-
feature_flags_names = self._split_storage.get_feature_flags_by_sets(sanitized_flag_sets)
433-
return feature_flags_names
432+
feature_flags_by_set = self._split_storage.get_feature_flags_by_sets(sanitized_flag_sets)
433+
if feature_flags_by_set is None:
434+
_LOGGER.warning("Fetching feature flags for flag set %s encountered an error, skipping this flag set." % (flag_sets))
435+
return []
436+
return feature_flags_by_set
434437

435438
def _build_impression( # pylint: disable=too-many-arguments
436439
self,

splitio/models/splits.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def __init__( # pylint: disable=too-many-arguments
9393
self._algo = HashAlgorithm.LEGACY
9494

9595
self._configurations = configurations
96-
self._sets = sets
96+
self._sets = set(sets) if sets is not None else set()
9797

9898
@property
9999
def name(self):

splitio/push/splitworker.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from splitio.models.splits import from_raw, Status
1111
from splitio.models.telemetry import UpdateFromSSE
1212
from splitio.push.parser import UpdateType
13-
13+
from splitio.util.storage_helper import update_feature_flag_storage
1414

1515
_LOGGER = logging.getLogger(__name__)
1616

@@ -88,17 +88,12 @@ def _run(self):
8888
try:
8989
if self._check_instant_ff_update(event):
9090
try:
91-
new_split = from_raw(json.loads(self._get_feature_flag_definition(event)))
92-
if new_split.status == Status.ACTIVE:
93-
self._feature_flag_storage.put(new_split)
94-
_LOGGER.debug('Feature flag %s is updated', new_split.name)
95-
for segment_name in new_split.get_segment_names():
96-
if self._segment_storage.get(segment_name) is None:
97-
_LOGGER.debug('Fetching new segment %s', segment_name)
98-
self._segment_handler(segment_name, event.change_number)
99-
else:
100-
self._feature_flag_storage.remove(new_split.name)
101-
self._feature_flag_storage.set_change_number(event.change_number)
91+
new_feature_flag = from_raw(json.loads(self._get_feature_flag_definition(event)))
92+
segment_list = update_feature_flag_storage(self._feature_flag_storage, [new_feature_flag], event.change_number)
93+
for segment_name in segment_list:
94+
if self._segment_storage.get(segment_name) is None:
95+
_LOGGER.debug('Fetching new segment %s', segment_name)
96+
self._segment_handler(segment_name, event.change_number)
10297
self._telemetry_runtime_producer.record_update_from_sse(UpdateFromSSE.SPLIT_UPDATE)
10398
continue
10499
except Exception as e:

splitio/storage/inmemmory.py

Lines changed: 76 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,79 @@
1313

1414
_LOGGER = logging.getLogger(__name__)
1515

16+
class FlagSetsFilter(object):
17+
"""Config Flagsets Filter storage."""
18+
19+
def __init__(self, flag_sets=[]):
20+
self.flag_sets = set(flag_sets)
21+
self.should_filter = any(flag_sets)
22+
23+
def set_exist(self, flag_set):
24+
if not self.should_filter:
25+
return True
26+
if not isinstance(flag_set, str) or flag_set == '':
27+
return False
28+
29+
return any(self.flag_sets.intersection(set([flag_set])))
30+
31+
def intersect(self, flag_sets):
32+
if not self.should_filter:
33+
return True
34+
if not isinstance(flag_sets, set) or len(flag_sets) == 0:
35+
return False
36+
return any(self.flag_sets.intersection(flag_sets))
37+
38+
39+
class FlagSets(object):
40+
"""InMemory Flagsets storage."""
41+
42+
def __init__(self, flag_sets=[]):
43+
self._lock = threading.RLock()
44+
self.sets_feature_flag_map = {}
45+
for flag_set in flag_sets:
46+
self.sets_feature_flag_map[flag_set] = set()
47+
48+
def flag_set_exist(self, flag_set):
49+
with self._lock:
50+
return flag_set in self.sets_feature_flag_map.keys()
51+
52+
def get_flag_set(self, flag_set):
53+
with self._lock:
54+
if self.flag_set_exist(flag_set):
55+
return self.sets_feature_flag_map[flag_set]
56+
57+
def add_flag_set(self, flag_set):
58+
with self._lock:
59+
if not self.flag_set_exist(flag_set):
60+
self.sets_feature_flag_map[flag_set] = set()
61+
62+
def remove_flag_set(self, flag_set):
63+
with self._lock:
64+
if self.flag_set_exist(flag_set):
65+
del self.sets_feature_flag_map[flag_set]
66+
67+
def add_feature_flag_to_flag_set(self, flag_set, feature_flag):
68+
with self._lock:
69+
if self.flag_set_exist(flag_set):
70+
self.sets_feature_flag_map[flag_set].add(feature_flag)
71+
72+
def remove_feature_flag_to_flag_set(self, flag_set, feature_flag):
73+
with self._lock:
74+
if self.flag_set_exist(flag_set):
75+
self.sets_feature_flag_map[flag_set].remove(feature_flag)
76+
1677

1778
class InMemorySplitStorage(SplitStorage):
18-
"""InMemory implementation of a split storage."""
79+
"""InMemory implementation of a feature flag storage."""
1980

2081
def __init__(self, flag_sets=[]):
2182
"""Constructor."""
2283
self._lock = threading.RLock()
2384
self._splits = {}
2485
self._change_number = -1
2586
self._traffic_types = Counter()
26-
self._sets_feature_flag_map = {}
27-
self.config_flag_sets_used = len(flag_sets)
28-
for flag_set in flag_sets:
29-
self._sets_feature_flag_map[flag_set] = set()
87+
self.flag_set = FlagSets(flag_sets)
88+
self.flag_set_filter = FlagSetsFilter(flag_sets)
3089

3190
def get(self, split_name):
3291
"""
@@ -82,11 +141,11 @@ def _put(self, split):
82141
self._increase_traffic_type_count(split.traffic_type_name)
83142
if split.sets is not None:
84143
for flag_set in split.sets:
85-
if flag_set not in self._sets_feature_flag_map.keys():
86-
if self.config_flag_sets_used > 0:
144+
if not self.flag_set.flag_set_exist(flag_set):
145+
if self.flag_set_filter.should_filter:
87146
continue
88-
self._sets_feature_flag_map[flag_set] = set()
89-
self._sets_feature_flag_map[flag_set].add(split.name)
147+
self.flag_set.add_flag_set(flag_set)
148+
self.flag_set.add_feature_flag_to_flag_set(flag_set, split.name)
90149

91150
def _remove(self, split_name):
92151
"""
@@ -118,9 +177,9 @@ def _remove_from_flag_sets(self, feature_flag):
118177
"""
119178
if feature_flag.sets is not None:
120179
for flag_set in feature_flag.sets:
121-
self._sets_feature_flag_map[flag_set].remove(feature_flag.name)
122-
if len(self._sets_feature_flag_map[flag_set]) == 0 and self.config_flag_sets_used == 0:
123-
del self._sets_feature_flag_map[flag_set]
180+
self.flag_set.remove_feature_flag_to_flag_set(flag_set, feature_flag.name)
181+
if len(self.flag_set.get_flag_set(flag_set)) == 0 and not self.flag_set_filter.should_filter:
182+
self.flag_set.remove_flag_set(flag_set)
124183

125184
def get_feature_flags_by_sets(self, sets):
126185
"""
@@ -135,19 +194,13 @@ def get_feature_flags_by_sets(self, sets):
135194
with self._lock:
136195
sets_to_fetch = []
137196
for flag_set in sets:
138-
if flag_set not in self._sets_feature_flag_map.keys():
139-
if self.config_flag_sets_used > 0:
140-
_LOGGER.warning("Flag set %s is not part of the configured flag set list, ignoring the request." % (flag_set))
141-
continue
142-
else:
143-
self._sets_feature_flag_map[flag_set] = set()
197+
if not self.flag_set.flag_set_exist(flag_set):
198+
_LOGGER.warning("Flag set %s is not part of the configured flag set list, ignoring it." % (flag_set))
199+
continue
144200
sets_to_fetch.append(flag_set)
145201

146-
if sets_to_fetch == []:
147-
return []
148-
149202
to_return = set()
150-
[to_return.update(self._sets_feature_flag_map[flag_set]) for flag_set in sets_to_fetch]
203+
[to_return.update(self.flag_set.get_flag_set(flag_set)) for flag_set in sets_to_fetch]
151204
return list(to_return)
152205

153206
def get_change_number(self):
@@ -260,10 +313,7 @@ def is_flag_set_exist(self, flag_set):
260313
:return: True if the flag_set exist. False otherwise.
261314
:rtype: bool
262315
"""
263-
if flag_set in self._sets_feature_flag_map.keys():
264-
return True
265-
return False
266-
316+
return self.flag_set.flag_set_exist(flag_set)
267317

268318
class InMemorySegmentStorage(SegmentStorage):
269319
"""In-memory implementation of a segment storage."""

0 commit comments

Comments
 (0)