Skip to content

Commit 775a421

Browse files
committed
Added support for NONE mode
1 parent 99fade2 commit 775a421

File tree

2 files changed

+160
-3
lines changed

2 files changed

+160
-3
lines changed

splitio/engine/impressions/adapters.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,9 @@ def record_unique_keys(self, uniques):
142142
"""
143143
bulk_mtks = _uniques_formatter(uniques)
144144
try:
145-
inserted = self._adapter_client.push_items(_MTK_QUEUE_KEY, *bulk_mtks)
145+
_LOGGER.debug("record_unique_keys")
146+
_LOGGER.debug(uniques)
147+
inserted = self._adapter_client.push_items(self._prefix + _MTK_QUEUE_KEY, *bulk_mtks)
146148
self._expire_keys(self._prefix + _MTK_QUEUE_KEY, _MTK_KEY_DEFAULT_TTL, inserted, len(bulk_mtks))
147149
return True
148150
except RedisAdapterException:

tests/integration/test_client_e2e.py

Lines changed: 157 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@
2020
from splitio.storage.adapters.redis import build, RedisAdapter
2121
from splitio.models import splits, segments
2222
from splitio.engine.impressions.impressions import Manager as ImpressionsManager, ImpressionsMode
23-
from splitio.engine.impressions.strategies import StrategyDebugMode, StrategyOptimizedMode
23+
from splitio.engine.impressions import set_classes
24+
from splitio.engine.impressions.strategies import StrategyDebugMode, StrategyOptimizedMode, StrategyNoneMode
2425
from splitio.engine.impressions.manager import Counter
2526
from splitio.engine.telemetry import TelemetryStorageConsumer, TelemetryStorageProducer
2627
from splitio.engine.impressions.manager import Counter as ImpressionsCounter
2728
from splitio.recorder.recorder import StandardRecorder, PipelinedRecorder
2829
from splitio.client.config import DEFAULT_CONFIG
29-
from splitio.sync.synchronizer import SplitTasks, SplitSynchronizers, Synchronizer
30+
from splitio.sync.synchronizer import SplitTasks, SplitSynchronizers, Synchronizer, RedisSynchronizer
3031
from splitio.sync.manager import Manager, RedisManager
3132
from splitio.sync.synchronizer import PluggableSynchronizer
3233

@@ -1721,3 +1722,157 @@ def test_track(self):
17211722
client,
17221723
('user1', 'user', 'conversion', 1, "{'prop1': 'value1'}")
17231724
)
1725+
1726+
class PluggableNoneIntegrationTests(object):
1727+
"""Pluggable storage-based integration tests."""
1728+
1729+
def setup_method(self):
1730+
"""Prepare storages with test data."""
1731+
metadata = SdkMetadata('python-1.2.3', 'some_ip', 'some_name')
1732+
self.pluggable_storage_adapter = StorageMockAdapter()
1733+
split_storage = PluggableSplitStorage(self.pluggable_storage_adapter, 'myprefix')
1734+
segment_storage = PluggableSegmentStorage(self.pluggable_storage_adapter, 'myprefix')
1735+
1736+
telemetry_pluggable_storage = PluggableTelemetryStorage(self.pluggable_storage_adapter, metadata, 'myprefix')
1737+
telemetry_producer = TelemetryStorageProducer(telemetry_pluggable_storage)
1738+
telemetry_consumer = TelemetryStorageConsumer(telemetry_pluggable_storage)
1739+
telemetry_runtime_producer = telemetry_producer.get_telemetry_runtime_producer()
1740+
1741+
storages = {
1742+
'splits': split_storage,
1743+
'segments': segment_storage,
1744+
'impressions': PluggableImpressionsStorage(self.pluggable_storage_adapter, metadata, 'myprefix'),
1745+
'events': PluggableEventsStorage(self.pluggable_storage_adapter, metadata, 'myprefix'),
1746+
'telemetry': telemetry_pluggable_storage
1747+
}
1748+
1749+
unique_keys_synchronizer, clear_filter_sync, unique_keys_task, \
1750+
clear_filter_task, impressions_count_sync, impressions_count_task, \
1751+
imp_strategy = set_classes('PLUGGABLE', ImpressionsMode.NONE, self.pluggable_storage_adapter, 'myprefix')
1752+
impmanager = ImpressionsManager(imp_strategy, telemetry_runtime_producer) # no listener
1753+
1754+
recorder = StandardRecorder(impmanager, storages['events'],
1755+
storages['impressions'], storages['telemetry'])
1756+
1757+
synchronizers = SplitSynchronizers(None, None, None, None,
1758+
impressions_count_sync,
1759+
None,
1760+
unique_keys_synchronizer,
1761+
clear_filter_sync
1762+
)
1763+
1764+
tasks = SplitTasks(None, None, None, None,
1765+
impressions_count_task,
1766+
None,
1767+
unique_keys_task,
1768+
clear_filter_task
1769+
)
1770+
1771+
synchronizer = RedisSynchronizer(synchronizers, tasks)
1772+
1773+
manager = RedisManager(synchronizer)
1774+
manager.start()
1775+
self.factory = SplitFactory('some_api_key',
1776+
storages,
1777+
True,
1778+
recorder,
1779+
manager,
1780+
sdk_ready_flag=None,
1781+
telemetry_producer=telemetry_producer,
1782+
telemetry_init_producer=telemetry_producer.get_telemetry_init_producer(),
1783+
) # pylint:disable=attribute-defined-outside-init
1784+
1785+
# Adding data to storage
1786+
split_fn = os.path.join(os.path.dirname(__file__), 'files', 'splitChanges.json')
1787+
with open(split_fn, 'r') as flo:
1788+
data = json.loads(flo.read())
1789+
for split in data['splits']:
1790+
self.pluggable_storage_adapter.set(split_storage._prefix.format(split_name=split['name']), split)
1791+
self.pluggable_storage_adapter.set(split_storage._split_till_prefix, data['till'])
1792+
1793+
segment_fn = os.path.join(os.path.dirname(__file__), 'files', 'segmentEmployeesChanges.json')
1794+
with open(segment_fn, 'r') as flo:
1795+
data = json.loads(flo.read())
1796+
self.pluggable_storage_adapter.set(segment_storage._prefix.format(segment_name=data['name']), set(data['added']))
1797+
self.pluggable_storage_adapter.set(segment_storage._segment_till_prefix.format(segment_name=data['name']), data['till'])
1798+
1799+
segment_fn = os.path.join(os.path.dirname(__file__), 'files', 'segmentHumanBeignsChanges.json')
1800+
with open(segment_fn, 'r') as flo:
1801+
data = json.loads(flo.read())
1802+
self.pluggable_storage_adapter.set(segment_storage._prefix.format(segment_name=data['name']), set(data['added']))
1803+
self.pluggable_storage_adapter.set(segment_storage._segment_till_prefix.format(segment_name=data['name']), data['till'])
1804+
self.client = self.factory.client()
1805+
1806+
1807+
def _validate_last_events(self, client, *to_validate):
1808+
"""Validate the last N impressions are present disregarding the order."""
1809+
event_storage = client._factory._get_storage('events')
1810+
events_raw = []
1811+
stored_events = self.pluggable_storage_adapter.pop_items(event_storage._events_queue_key)
1812+
if stored_events is not None:
1813+
events_raw = [json.loads(im) for im in stored_events]
1814+
1815+
as_tup_set = set(
1816+
(i['e']['key'], i['e']['trafficTypeName'], i['e']['eventTypeId'], i['e']['value'], str(i['e']['properties']))
1817+
for i in events_raw
1818+
)
1819+
assert as_tup_set == set(to_validate)
1820+
1821+
def test_get_treatment(self):
1822+
"""Test client.get_treatment()."""
1823+
assert self.client.get_treatment('user1', 'sample_feature') == 'on'
1824+
assert self.client.get_treatment('invalidKey', 'sample_feature') == 'off'
1825+
assert self.pluggable_storage_adapter._keys['myprefix.SPLITIO.impressions'] == []
1826+
1827+
def test_get_treatments(self):
1828+
"""Test client.get_treatments()."""
1829+
result = self.client.get_treatments('user1', ['sample_feature'])
1830+
assert len(result) == 1
1831+
assert result['sample_feature'] == 'on'
1832+
1833+
result = self.client.get_treatments('invalidKey', ['sample_feature'])
1834+
assert len(result) == 1
1835+
assert result['sample_feature'] == 'off'
1836+
1837+
result = self.client.get_treatments('invalidKey', ['invalid_feature'])
1838+
assert len(result) == 1
1839+
assert result['invalid_feature'] == 'control'
1840+
assert self.pluggable_storage_adapter._keys['myprefix.SPLITIO.impressions'] == []
1841+
1842+
def test_get_treatments_with_config(self):
1843+
"""Test client.get_treatments_with_config()."""
1844+
result = self.client.get_treatments_with_config('user1', ['sample_feature'])
1845+
assert len(result) == 1
1846+
assert result['sample_feature'] == ('on', '{"size":15,"test":20}')
1847+
1848+
result = self.client.get_treatments_with_config('invalidKey2', ['sample_feature'])
1849+
assert len(result) == 1
1850+
assert result['sample_feature'] == ('off', None)
1851+
1852+
result = self.client.get_treatments_with_config('invalidKey', ['invalid_feature'])
1853+
assert len(result) == 1
1854+
assert result['invalid_feature'] == ('control', None)
1855+
assert self.pluggable_storage_adapter._keys['myprefix.SPLITIO.impressions'] == []
1856+
1857+
def test_track(self):
1858+
"""Test client.track()."""
1859+
assert(self.client.track('user1', 'user', 'conversion', 1, {"prop1": "value1"}))
1860+
assert(not self.client.track(None, 'user', 'conversion'))
1861+
assert(not self.client.track('user1', None, 'conversion'))
1862+
assert(not self.client.track('user1', 'user', None))
1863+
self._validate_last_events(
1864+
self.client,
1865+
('user1', 'user', 'conversion', 1, "{'prop1': 'value1'}")
1866+
)
1867+
1868+
def test_mtk(self):
1869+
self.client.get_treatment('user1', 'sample_feature')
1870+
self.client.get_treatment('invalidKey', 'sample_feature')
1871+
self.client.get_treatment('invalidKey2', 'sample_feature')
1872+
self.client.get_treatment('user22', 'invalidFeature')
1873+
event = threading.Event()
1874+
self.factory.destroy(event)
1875+
event.wait()
1876+
assert(json.loads(self.pluggable_storage_adapter._keys['myprefix.SPLITIO.uniquekeys'][0])["f"] =="sample_feature")
1877+
assert(json.loads(self.pluggable_storage_adapter._keys['myprefix.SPLITIO.uniquekeys'][0])["ks"].sort() ==
1878+
["invalidKey2", "invalidKey", "user1"].sort())

0 commit comments

Comments
 (0)