Skip to content

Commit 343edac

Browse files
committed
used get_many in pluggable storage instead of individual keys
1 parent 3ad6bf5 commit 343edac

File tree

3 files changed

+34
-85
lines changed

3 files changed

+34
-85
lines changed

splitio/storage/pluggable.py

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class PluggableSplitStorageBase(SplitStorage):
1818
"""InMemory implementation of a feature flag storage."""
1919

2020
_FEATURE_FLAG_NAME_LENGTH = 19
21+
_TILL_LENGTH = 4
2122

2223
def __init__(self, pluggable_adapter, prefix=None, config_flag_sets=[]):
2324
"""
@@ -137,15 +138,6 @@ def get_split_names(self):
137138
"""
138139
pass
139140

140-
def get_all(self):
141-
"""
142-
Return all the feature flags.
143-
144-
:return: List of all the feature flags.
145-
:rtype: list
146-
"""
147-
pass
148-
149141
def traffic_type_exists(self, traffic_type_name):
150142
"""
151143
Return whether the traffic type exists in at least one feature flag in cache.
@@ -336,26 +328,16 @@ def get_split_names(self):
336328
:rtype: list(str)
337329
"""
338330
try:
339-
return [feature_flag.name for feature_flag in self.get_all()]
331+
keys = []
332+
for key in self._pluggable_adapter.get_keys_by_prefix(self._prefix[:-self._FEATURE_FLAG_NAME_LENGTH]):
333+
if key[-self._TILL_LENGTH:] != 'till':
334+
keys.append(key[len(self._prefix[:-self._FEATURE_FLAG_NAME_LENGTH]):])
335+
return keys
340336
except Exception:
341337
_LOGGER.error('Error getting feature flag names from storage')
342338
_LOGGER.debug('Error: ', exc_info=True)
343339
return None
344340

345-
def get_all(self):
346-
"""
347-
Return all the feature flags.
348-
349-
:return: List of all the feature flags.
350-
:rtype: list
351-
"""
352-
try:
353-
return [splits.from_raw(self._pluggable_adapter.get(key)) for key in self._pluggable_adapter.get_keys_by_prefix(self._prefix[:-self._FEATURE_FLAG_NAME_LENGTH])]
354-
except Exception:
355-
_LOGGER.error('Error getting feature flag keys from storage')
356-
_LOGGER.debug('Error: ', exc_info=True)
357-
return None
358-
359341
def traffic_type_exists(self, traffic_type_name):
360342
"""
361343
Return whether the traffic type exists in at least one feature flag in cache.
@@ -381,7 +363,11 @@ def get_all_splits(self):
381363
:rtype: list
382364
"""
383365
try:
384-
return self.get_all()
366+
keys = []
367+
for key in self._pluggable_adapter.get_keys_by_prefix(self._prefix[:-self._FEATURE_FLAG_NAME_LENGTH]):
368+
if key[-self._TILL_LENGTH:] != 'till':
369+
keys.append(key)
370+
return [splits.from_raw(feature_flag) for feature_flag in self._pluggable_adapter.get_many(keys)]
385371
except Exception:
386372
_LOGGER.error('Error fetching feature flags from storage')
387373
_LOGGER.debug('Error: ', exc_info=True)
@@ -498,26 +484,16 @@ async def get_split_names(self):
498484
:rtype: list(str)
499485
"""
500486
try:
501-
return [feature_flag.name for feature_flag in await self.get_all()]
487+
keys = []
488+
for key in await self._pluggable_adapter.get_keys_by_prefix(self._prefix[:-self._FEATURE_FLAG_NAME_LENGTH]):
489+
if key[-self._TILL_LENGTH:] != 'till':
490+
keys.append(key[len(self._prefix[:-self._FEATURE_FLAG_NAME_LENGTH]):])
491+
return keys
502492
except Exception:
503493
_LOGGER.error('Error getting feature flag names from storage')
504494
_LOGGER.debug('Error: ', exc_info=True)
505495
return None
506496

507-
async def get_all(self):
508-
"""
509-
Return all the feature flags.
510-
511-
:return: List of all the feature flags.
512-
:rtype: list
513-
"""
514-
try:
515-
return [splits.from_raw(await self._pluggable_adapter.get(key)) for key in await self._pluggable_adapter.get_keys_by_prefix(self._prefix[:-self._FEATURE_FLAG_NAME_LENGTH])]
516-
except Exception:
517-
_LOGGER.error('Error getting feature flag keys from storage')
518-
_LOGGER.debug('Error: ', exc_info=True)
519-
return None
520-
521497
async def traffic_type_exists(self, traffic_type_name):
522498
"""
523499
Return whether the traffic type exists in at least one feature flag in cache.
@@ -543,7 +519,11 @@ async def get_all_splits(self):
543519
:rtype: list
544520
"""
545521
try:
546-
return await self.get_all()
522+
keys = []
523+
for key in await self._pluggable_adapter.get_keys_by_prefix(self._prefix[:-self._FEATURE_FLAG_NAME_LENGTH]):
524+
if key[-self._TILL_LENGTH:] != 'till':
525+
keys.append(key)
526+
return [splits.from_raw(feature_flag) for feature_flag in await self._pluggable_adapter.get_many(keys)]
547527
except Exception:
548528
_LOGGER.error('Error fetching feature flags from storage')
549529
_LOGGER.debug('Error: ', exc_info=True)

tests/integration/test_pluggable_integration.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ def test_put_fetch(self):
2424
with open(split_fn, 'r') as flo:
2525
data = json.loads(flo.read())
2626
for split in data['splits']:
27-
adapter.set(storage._prefix.format(split_name=split['name']), split)
27+
adapter.set(storage._prefix.format(feature_flag_name=split['name']), split)
2828
adapter.increment(storage._traffic_type_prefix.format(traffic_type_name=split['trafficTypeName']), 1)
29-
adapter.set(storage._split_till_prefix, data['till'])
29+
adapter.set(storage._feature_flag_till_prefix, data['till'])
3030

3131
split_objects = [splits.from_raw(raw) for raw in data['splits']]
3232
for split_object in split_objects:
@@ -53,7 +53,7 @@ def test_put_fetch(self):
5353
assert len(original_condition.matchers) == len(fetched_condition.matchers)
5454
assert len(original_condition.partitions) == len(fetched_condition.partitions)
5555

56-
adapter.set(storage._split_till_prefix, data['till'])
56+
adapter.set(storage._feature_flag_till_prefix, data['till'])
5757
assert storage.get_change_number() == data['till']
5858

5959
assert storage.is_valid_traffic_type('user') is True
@@ -90,9 +90,9 @@ def test_get_all(self):
9090
with open(split_fn, 'r') as flo:
9191
data = json.loads(flo.read())
9292
for split in data['splits']:
93-
adapter.set(storage._prefix.format(split_name=split['name']), split)
93+
adapter.set(storage._prefix.format(feature_flag_name=split['name']), split)
9494
adapter.increment(storage._traffic_type_prefix.format(traffic_type_name=split['trafficTypeName']), 1)
95-
adapter.set(storage._split_till_prefix, data['till'])
95+
adapter.set(storage._feature_flag_till_prefix, data['till'])
9696

9797
split_objects = [splits.from_raw(raw) for raw in data['splits']]
9898
original_splits = {split.name: split for split in split_objects}
@@ -261,9 +261,9 @@ async def test_put_fetch(self):
261261
with open(split_fn, 'r') as flo:
262262
data = json.loads(flo.read())
263263
for split in data['splits']:
264-
await adapter.set(storage._prefix.format(split_name=split['name']), split)
264+
await adapter.set(storage._prefix.format(feature_flag_name=split['name']), split)
265265
await adapter.increment(storage._traffic_type_prefix.format(traffic_type_name=split['trafficTypeName']), 1)
266-
await adapter.set(storage._split_till_prefix, data['till'])
266+
await adapter.set(storage._feature_flag_till_prefix, data['till'])
267267

268268
split_objects = [splits.from_raw(raw) for raw in data['splits']]
269269
for split_object in split_objects:
@@ -290,7 +290,7 @@ async def test_put_fetch(self):
290290
assert len(original_condition.matchers) == len(fetched_condition.matchers)
291291
assert len(original_condition.partitions) == len(fetched_condition.partitions)
292292

293-
await adapter.set(storage._split_till_prefix, data['till'])
293+
await adapter.set(storage._feature_flag_till_prefix, data['till'])
294294
assert await storage.get_change_number() == data['till']
295295

296296
assert await storage.is_valid_traffic_type('user') is True
@@ -328,9 +328,9 @@ async def test_get_all(self):
328328
with open(split_fn, 'r') as flo:
329329
data = json.loads(flo.read())
330330
for split in data['splits']:
331-
await adapter.set(storage._prefix.format(split_name=split['name']), split)
331+
await adapter.set(storage._prefix.format(feature_flag_name=split['name']), split)
332332
await adapter.increment(storage._traffic_type_prefix.format(traffic_type_name=split['trafficTypeName']), 1)
333-
await adapter.set(storage._split_till_prefix, data['till'])
333+
await adapter.set(storage._feature_flag_till_prefix, data['till'])
334334

335335
split_objects = [splits.from_raw(raw) for raw in data['splits']]
336336
original_splits = {split.name: split for split in split_objects}

tests/storage/test_pluggable.py

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,9 @@ async def get_keys_by_prefix(self, prefix):
196196
async def get_many(self, keys):
197197
async with self._lock:
198198
returned_keys = []
199-
for key in keys:
200-
if key in self._keys:
199+
for key in self._keys:
200+
if key in keys:
201201
returned_keys.append(self._keys[key])
202-
else:
203-
returned_keys.append(None)
204202
return returned_keys
205203

206204
async def add_items(self, key, added_items):
@@ -336,20 +334,6 @@ def test_get_split_names(self):
336334
self.mock_adapter.set(pluggable_split_storage._prefix.format(feature_flag_name=split2.name), split2.to_json())
337335
assert(pluggable_split_storage.get_split_names() == [split1.name, split2.name])
338336

339-
def test_get_all(self):
340-
self.mock_adapter._keys = {}
341-
for sprefix in [None, 'myprefix']:
342-
pluggable_split_storage = PluggableSplitStorage(self.mock_adapter, prefix=sprefix)
343-
split1 = splits.from_raw(splits_json['splitChange1_2']['splits'][0])
344-
split2_temp = splits_json['splitChange1_2']['splits'][0].copy()
345-
split2_temp['name'] = 'another_split'
346-
split2 = splits.from_raw(split2_temp)
347-
348-
self.mock_adapter.set(pluggable_split_storage._prefix.format(feature_flag_name=split1.name), split1.to_json())
349-
self.mock_adapter.set(pluggable_split_storage._prefix.format(feature_flag_name=split2.name), split2.to_json())
350-
all_splits = pluggable_split_storage.get_all()
351-
assert([all_splits[0].to_json(), all_splits[1].to_json()] == [split1.to_json(), split2.to_json()])
352-
353337
# TODO: To be added when producer mode is aupported
354338
# def test_kill_locally(self):
355339
# self.mock_adapter._keys = {}
@@ -474,23 +458,8 @@ async def test_get_split_names(self):
474458
split2 = splits.from_raw(split2_temp)
475459
await self.mock_adapter.set(pluggable_split_storage._prefix.format(feature_flag_name=split1.name), split1.to_json())
476460
await self.mock_adapter.set(pluggable_split_storage._prefix.format(feature_flag_name=split2.name), split2.to_json())
477-
assert(await pluggable_split_storage.get_split_names() == [split1.name, split2.name])
478-
479-
@pytest.mark.asyncio
480-
async def test_get_all(self):
481-
self.mock_adapter._keys = {}
482-
for sprefix in [None, 'myprefix']:
483-
pluggable_split_storage = PluggableSplitStorageAsync(self.mock_adapter, prefix=sprefix)
484-
split1 = splits.from_raw(splits_json['splitChange1_2']['splits'][0])
485-
split2_temp = splits_json['splitChange1_2']['splits'][0].copy()
486-
split2_temp['name'] = 'another_split'
487-
split2 = splits.from_raw(split2_temp)
488-
489-
await self.mock_adapter.set(pluggable_split_storage._prefix.format(feature_flag_name=split1.name), split1.to_json())
490-
await self.mock_adapter.set(pluggable_split_storage._prefix.format(feature_flag_name=split2.name), split2.to_json())
491-
all_splits = await pluggable_split_storage.get_all()
492-
assert([all_splits[0].to_json(), all_splits[1].to_json()] == [split1.to_json(), split2.to_json()])
493461

462+
assert(await pluggable_split_storage.get_split_names() == [split1.name, split2.name])
494463

495464
class PluggableSegmentStorageTests(object):
496465
"""In memory split storage test cases."""

0 commit comments

Comments
 (0)