Skip to content

Commit b7391b4

Browse files
committed
Update factory and tests
1 parent 50f5b76 commit b7391b4

File tree

8 files changed

+140
-36
lines changed

8 files changed

+140
-36
lines changed

splitio/client/client.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def __init__(self, factory, recorder, labels_enabled=True, fallback_treatments_c
6363
self._feature_flag_storage = factory._get_storage('splits') # pylint: disable=protected-access
6464
self._segment_storage = factory._get_storage('segments') # pylint: disable=protected-access
6565
self._events_storage = factory._get_storage('events') # pylint: disable=protected-access
66-
self._evaluator = Evaluator(self._splitter)
66+
self._evaluator = Evaluator(self._splitter, fallback_treatments_configuration)
6767
self._telemetry_evaluation_producer = self._factory._telemetry_evaluation_producer
6868
self._telemetry_init_producer = self._factory._telemetry_init_producer
6969
self._fallback_treatments_configuration = fallback_treatments_configuration
@@ -344,7 +344,7 @@ def _get_treatment(self, method, key, feature, attributes=None, evaluation_optio
344344
result = self._get_fallback_eval_results(self._FAILED_EVAL_RESULT, feature)
345345

346346
properties = self._get_properties(evaluation_options)
347-
if result['impression']['label'].find(Label.SPLIT_NOT_FOUND) == -1:
347+
if result['impression']['label'] == None or (result['impression']['label'] != None and result['impression']['label'].find(Label.SPLIT_NOT_FOUND) == -1):
348348
impression_decorated = self._build_impression(key, bucketing, feature, result, properties)
349349
self._record_stats([(impression_decorated, attributes)], start, method)
350350

@@ -647,7 +647,7 @@ def _get_treatments(self, key, features, method, attributes=None, evaluation_opt
647647
properties = self._get_properties(evaluation_options)
648648
imp_decorated_attrs = [
649649
(i, attributes) for i in self._build_impressions(key, bucketing, results, properties)
650-
if i.Impression.label.find(Label.SPLIT_NOT_FOUND) == -1
650+
if i.Impression.label == None or (i.Impression.label != None and i.Impression.label.find(Label.SPLIT_NOT_FOUND)) == -1
651651
]
652652
self._record_stats(imp_decorated_attrs, start, method)
653653

@@ -844,7 +844,7 @@ async def _get_treatment(self, method, key, feature, attributes=None, evaluation
844844
result = self._get_fallback_eval_results(self._FAILED_EVAL_RESULT, feature)
845845

846846
properties = self._get_properties(evaluation_options)
847-
if result['impression']['label'].find(Label.SPLIT_NOT_FOUND) == -1:
847+
if result['impression']['label'] == None or (result['impression']['label'] != None and result['impression']['label'].find(Label.SPLIT_NOT_FOUND) == -1):
848848
impression_decorated = self._build_impression(key, bucketing, feature, result, properties)
849849
await self._record_stats([(impression_decorated, attributes)], start, method)
850850
return result['treatment'], result['configurations']
@@ -1060,7 +1060,7 @@ async def _get_treatments(self, key, features, method, attributes=None, evaluati
10601060
properties = self._get_properties(evaluation_options)
10611061
imp_decorated_attrs = [
10621062
(i, attributes) for i in self._build_impressions(key, bucketing, results, properties)
1063-
if i.Impression.label != Label.SPLIT_NOT_FOUND
1063+
if i.Impression.label == None or (i.Impression.label != None and i.Impression.label.find(Label.SPLIT_NOT_FOUND)) == -1
10641064
]
10651065
await self._record_stats(imp_decorated_attrs, start, method)
10661066

splitio/client/factory.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ def __init__( # pylint: disable=too-many-arguments
170170
telemetry_producer=None,
171171
telemetry_init_producer=None,
172172
telemetry_submitter=None,
173-
preforked_initialization=False
173+
preforked_initialization=False,
174+
fallback_treatments_configuration=None
174175
):
175176
"""
176177
Class constructor.
@@ -201,6 +202,7 @@ def __init__( # pylint: disable=too-many-arguments
201202
self._ready_time = get_current_epoch_time_ms()
202203
_LOGGER.debug("Running in threading mode")
203204
self._sdk_internal_ready_flag = sdk_ready_flag
205+
self._fallback_treatments_configuration = fallback_treatments_configuration
204206
self._start_status_updater()
205207

206208
def _start_status_updater(self):
@@ -242,7 +244,7 @@ def client(self):
242244
This client is only a set of references to structures hold by the factory.
243245
Creating one a fast operation and safe to be used anywhere.
244246
"""
245-
return Client(self, self._recorder, self._labels_enabled)
247+
return Client(self, self._recorder, self._labels_enabled, self._fallback_treatments_configuration)
246248

247249
def manager(self):
248250
"""
@@ -338,7 +340,8 @@ def __init__( # pylint: disable=too-many-arguments
338340
telemetry_init_producer=None,
339341
telemetry_submitter=None,
340342
manager_start_task=None,
341-
api_client=None
343+
api_client=None,
344+
fallback_treatments_configuration=None
342345
):
343346
"""
344347
Class constructor.
@@ -372,6 +375,7 @@ def __init__( # pylint: disable=too-many-arguments
372375
self._sdk_ready_flag = asyncio.Event()
373376
self._ready_task = asyncio.get_running_loop().create_task(self._update_status_when_ready_async())
374377
self._api_client = api_client
378+
self._fallback_treatments_configuration = fallback_treatments_configuration
375379

376380
async def _update_status_when_ready_async(self):
377381
"""Wait until the sdk is ready and update the status for async mode."""
@@ -460,7 +464,7 @@ def client(self):
460464
This client is only a set of references to structures hold by the factory.
461465
Creating one a fast operation and safe to be used anywhere.
462466
"""
463-
return ClientAsync(self, self._recorder, self._labels_enabled)
467+
return ClientAsync(self, self._recorder, self._labels_enabled, self._fallback_treatments_configuration)
464468

465469
def _wrap_impression_listener(listener, metadata):
466470
"""
@@ -623,15 +627,16 @@ def _build_in_memory_factory(api_key, cfg, sdk_url=None, events_url=None, # pyl
623627
synchronizer._split_synchronizers._segment_sync.shutdown()
624628

625629
return SplitFactory(api_key, storages, cfg['labelsEnabled'],
626-
recorder, manager, None, telemetry_producer, telemetry_init_producer, telemetry_submitter, preforked_initialization=preforked_initialization)
630+
recorder, manager, None, telemetry_producer, telemetry_init_producer, telemetry_submitter, preforked_initialization=preforked_initialization,
631+
fallback_treatments_configuration=cfg['fallbackTreatmentsConfiguration'])
627632

628633
initialization_thread = threading.Thread(target=manager.start, name="SDKInitializer", daemon=True)
629634
initialization_thread.start()
630635

631636
return SplitFactory(api_key, storages, cfg['labelsEnabled'],
632637
recorder, manager, sdk_ready_flag,
633638
telemetry_producer, telemetry_init_producer,
634-
telemetry_submitter)
639+
telemetry_submitter, fallback_treatments_configuration=cfg['fallbackTreatmentsConfiguration'])
635640

636641
async def _build_in_memory_factory_async(api_key, cfg, sdk_url=None, events_url=None, # pylint:disable=too-many-arguments,too-many-localsa
637642
auth_api_base_url=None, streaming_api_base_url=None, telemetry_api_base_url=None,
@@ -750,7 +755,7 @@ async def _build_in_memory_factory_async(api_key, cfg, sdk_url=None, events_url=
750755
recorder, manager,
751756
telemetry_producer, telemetry_init_producer,
752757
telemetry_submitter, manager_start_task=manager_start_task,
753-
api_client=http_client)
758+
api_client=http_client, fallback_treatments_configuration=cfg['fallbackTreatmentsConfiguration'])
754759

755760
def _build_redis_factory(api_key, cfg):
756761
"""Build and return a split factory with redis-based storage."""
@@ -828,7 +833,8 @@ def _build_redis_factory(api_key, cfg):
828833
manager,
829834
sdk_ready_flag=None,
830835
telemetry_producer=telemetry_producer,
831-
telemetry_init_producer=telemetry_init_producer
836+
telemetry_init_producer=telemetry_init_producer,
837+
fallback_treatments_configuration=cfg['fallbackTreatmentsConfiguration']
832838
)
833839
redundant_factory_count, active_factory_count = _get_active_and_redundant_count()
834840
storages['telemetry'].record_active_and_redundant_factories(active_factory_count, redundant_factory_count)
@@ -910,7 +916,8 @@ async def _build_redis_factory_async(api_key, cfg):
910916
manager,
911917
telemetry_producer=telemetry_producer,
912918
telemetry_init_producer=telemetry_init_producer,
913-
telemetry_submitter=telemetry_submitter
919+
telemetry_submitter=telemetry_submitter,
920+
fallback_treatments_configuration=cfg['fallbackTreatmentsConfiguration']
914921
)
915922
redundant_factory_count, active_factory_count = _get_active_and_redundant_count()
916923
await storages['telemetry'].record_active_and_redundant_factories(active_factory_count, redundant_factory_count)
@@ -992,7 +999,8 @@ def _build_pluggable_factory(api_key, cfg):
992999
manager,
9931000
sdk_ready_flag=None,
9941001
telemetry_producer=telemetry_producer,
995-
telemetry_init_producer=telemetry_init_producer
1002+
telemetry_init_producer=telemetry_init_producer,
1003+
fallback_treatments_configuration=cfg['fallbackTreatmentsConfiguration']
9961004
)
9971005
redundant_factory_count, active_factory_count = _get_active_and_redundant_count()
9981006
storages['telemetry'].record_active_and_redundant_factories(active_factory_count, redundant_factory_count)
@@ -1072,7 +1080,8 @@ async def _build_pluggable_factory_async(api_key, cfg):
10721080
manager,
10731081
telemetry_producer=telemetry_producer,
10741082
telemetry_init_producer=telemetry_init_producer,
1075-
telemetry_submitter=telemetry_submitter
1083+
telemetry_submitter=telemetry_submitter,
1084+
fallback_treatments_configuration=cfg['fallbackTreatmentsConfiguration']
10761085
)
10771086
redundant_factory_count, active_factory_count = _get_active_and_redundant_count()
10781087
await storages['telemetry'].record_active_and_redundant_factories(active_factory_count, redundant_factory_count)
@@ -1150,6 +1159,7 @@ def _build_localhost_factory(cfg):
11501159
telemetry_producer=telemetry_producer,
11511160
telemetry_init_producer=telemetry_producer.get_telemetry_init_producer(),
11521161
telemetry_submitter=LocalhostTelemetrySubmitter(),
1162+
fallback_treatments_configuration=cfg['fallbackTreatmentsConfiguration']
11531163
)
11541164

11551165
async def _build_localhost_factory_async(cfg):
@@ -1220,7 +1230,8 @@ async def _build_localhost_factory_async(cfg):
12201230
telemetry_producer=telemetry_producer,
12211231
telemetry_init_producer=telemetry_producer.get_telemetry_init_producer(),
12221232
telemetry_submitter=LocalhostTelemetrySubmitterAsync(),
1223-
manager_start_task=manager_start_task
1233+
manager_start_task=manager_start_task,
1234+
fallback_treatments_configuration=cfg['fallbackTreatmentsConfiguration']
12241235
)
12251236

12261237
def get_factory(api_key, **kwargs):

splitio/storage/adapters/redis.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ def _build_default_client(config): # pylint: disable=too-many-locals
715715
unix_socket_path = config.get('redisUnixSocketPath', None)
716716
encoding = config.get('redisEncoding', 'utf-8')
717717
encoding_errors = config.get('redisEncodingErrors', 'strict')
718-
errors = config.get('redisErrors', None)
718+
# errors = config.get('redisErrors', None)
719719
decode_responses = config.get('redisDecodeResponses', True)
720720
retry_on_timeout = config.get('redisRetryOnTimeout', False)
721721
ssl = config.get('redisSsl', False)
@@ -740,7 +740,7 @@ def _build_default_client(config): # pylint: disable=too-many-locals
740740
unix_socket_path=unix_socket_path,
741741
encoding=encoding,
742742
encoding_errors=encoding_errors,
743-
errors=errors,
743+
# errors=errors, Starting from redis 6.0.0 errors argument is removed
744744
decode_responses=decode_responses,
745745
retry_on_timeout=retry_on_timeout,
746746
ssl=ssl,

tests/client/test_factory.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
from splitio.storage import redis, inmemmory, pluggable
1414
from splitio.tasks.util import asynctask
1515
from splitio.engine.impressions.impressions import Manager as ImpressionsManager
16+
from splitio.models.fallback_config import FallbackConfig, FallbackTreatmentsConfiguration
17+
from splitio.models.fallback_treatment import FallbackTreatment
1618
from splitio.sync.manager import Manager, ManagerAsync
1719
from splitio.sync.synchronizer import Synchronizer, SynchronizerAsync, SplitSynchronizers, SplitTasks
1820
from splitio.sync.split import SplitSynchronizer, SplitSynchronizerAsync
@@ -94,7 +96,7 @@ def test_redis_client_creation(self, mocker):
9496
"""Test that a client with redis storage is created correctly."""
9597
strict_redis_mock = mocker.Mock()
9698
mocker.patch('splitio.storage.adapters.redis.StrictRedis', new=strict_redis_mock)
97-
99+
fallback_treatments_configuration = FallbackTreatmentsConfiguration(FallbackConfig(FallbackTreatment("on")))
98100
config = {
99101
'labelsEnabled': False,
100102
'impressionListener': 123,
@@ -119,7 +121,8 @@ def test_redis_client_creation(self, mocker):
119121
'redisSslCertReqs': 'some_cert_req',
120122
'redisSslCaCerts': 'some_ca_cert',
121123
'redisMaxConnections': 999,
122-
'flagSetsFilter': ['set_1']
124+
'flagSetsFilter': ['set_1'],
125+
'fallbackTreatmentsConfiguration': fallback_treatments_configuration
123126
}
124127
factory = get_factory('some_api_key', config=config)
125128
class TelemetrySubmitterMock():
@@ -133,6 +136,7 @@ def synchronize_config(*_):
133136
assert isinstance(factory._get_storage('events'), redis.RedisEventsStorage)
134137

135138
assert factory._get_storage('splits').flag_set_filter.flag_sets == set([])
139+
assert factory._fallback_treatments_configuration == fallback_treatments_configuration
136140

137141
adapter = factory._get_storage('splits')._redis
138142
assert adapter == factory._get_storage('segments')._redis
@@ -153,7 +157,7 @@ def synchronize_config(*_):
153157
unix_socket_path='/some_path',
154158
encoding='utf-8',
155159
encoding_errors='non-strict',
156-
errors=True,
160+
# errors=True,
157161
decode_responses=True,
158162
retry_on_timeout=True,
159163
ssl=True,
@@ -705,10 +709,13 @@ class SplitFactoryAsyncTests(object):
705709

706710
@pytest.mark.asyncio
707711
async def test_flag_sets_counts(self):
712+
fallback_treatments_configuration = FallbackTreatmentsConfiguration(FallbackConfig(FallbackTreatment("on")))
708713
factory = await get_factory_async("none", config={
709714
'flagSetsFilter': ['set1', 'set2', 'set3'],
710-
'streamEnabled': False
715+
'streamEnabled': False,
716+
'fallbackTreatmentsConfiguration': fallback_treatments_configuration
711717
})
718+
assert factory._fallback_treatments_configuration == fallback_treatments_configuration
712719
assert factory._telemetry_init_producer._telemetry_storage._tel_config._flag_sets == 3
713720
assert factory._telemetry_init_producer._telemetry_storage._tel_config._flag_sets_invalid == 0
714721
await factory.destroy()

tests/client/test_input_validator.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Unit tests for the input_validator module."""
22
import pytest
3+
import logging
34

45
from splitio.client.factory import SplitFactory, get_factory, SplitFactoryAsync, get_factory_async
56
from splitio.client.client import CONTROL, Client, _LOGGER as _logger, ClientAsync
@@ -9,6 +10,7 @@
910
InMemorySplitStorage, InMemorySplitStorageAsync, InMemoryRuleBasedSegmentStorage, InMemoryRuleBasedSegmentStorageAsync
1011
from splitio.models.splits import Split
1112
from splitio.client import input_validator
13+
from splitio.client.manager import SplitManager, SplitManagerAsync
1214
from splitio.recorder.recorder import StandardRecorder, StandardRecorderAsync
1315
from splitio.engine.telemetry import TelemetryStorageProducer, TelemetryStorageProducerAsync
1416
from splitio.engine.impressions.impressions import Manager as ImpressionManager

0 commit comments

Comments
 (0)