2828from splitio .events .events_manager_config import EventsManagerConfig
2929from splitio .events .events_task import EventsTask
3030from splitio .models import splits , segments , rule_based_segments
31+ from splitio .models .events import SdkEvent
3132from splitio .models .fallback_config import FallbackTreatmentsConfiguration , FallbackTreatmentCalculator
3233from splitio .models .fallback_treatment import FallbackTreatment
3334from splitio .recorder .recorder import StandardRecorder , PipelinedRecorder , StandardRecorderAsync , PipelinedRecorderAsync
@@ -2424,6 +2425,181 @@ def clear_cache(self):
24242425 for key in keys_to_delete :
24252426 redis_client .delete (key )
24262427
2428+ class InMemoryEventsNotificationTests (object ):
2429+ """Inmemory storage-based events notification tests."""
2430+
2431+ ready_flag = False
2432+ timeout_flag = False
2433+
2434+ def test_sdk_timeout_fire (self ):
2435+ """Prepare storages with test data."""
2436+ factory2 = get_factory ('some_api_key' )
2437+ client = factory2 .client ()
2438+ client .on (SdkEvent .SDK_READY_TIMED_OUT , self ._timeout_callback )
2439+ try :
2440+ factory2 .block_until_ready (1 )
2441+ except Exception as e :
2442+ print (e )
2443+ pass
2444+
2445+ time .sleep (1 )
2446+ assert self .timeout_flag
2447+
2448+ """Shut down the factory."""
2449+ event = threading .Event ()
2450+ factory2 .destroy (event )
2451+ event .wait ()
2452+
2453+ def test_sdk_ready (self ):
2454+ """Prepare storages with test data."""
2455+ events_queue = queue .Queue ()
2456+ split_storage = InMemorySplitStorage (events_queue )
2457+ segment_storage = InMemorySegmentStorage (events_queue )
2458+ rb_segment_storage = InMemoryRuleBasedSegmentStorage (events_queue )
2459+
2460+ split_fn = os .path .join (os .path .dirname (__file__ ), 'files' , 'splitChanges.json' )
2461+ with open (split_fn , 'r' ) as flo :
2462+ data = json .loads (flo .read ())
2463+ for split in data ['ff' ]['d' ]:
2464+ split_storage .update ([splits .from_raw (split )], [], 0 )
2465+
2466+ for rbs in data ['rbs' ]['d' ]:
2467+ rb_segment_storage .update ([rule_based_segments .from_raw (rbs )], [], 0 )
2468+
2469+ segment_fn = os .path .join (os .path .dirname (__file__ ), 'files' , 'segmentEmployeesChanges.json' )
2470+ with open (segment_fn , 'r' ) as flo :
2471+ data = json .loads (flo .read ())
2472+ segment_storage .put (segments .from_raw (data ))
2473+
2474+ segment_fn = os .path .join (os .path .dirname (__file__ ), 'files' , 'segmentHumanBeignsChanges.json' )
2475+ with open (segment_fn , 'r' ) as flo :
2476+ data = json .loads (flo .read ())
2477+ segment_storage .put (segments .from_raw (data ))
2478+
2479+ telemetry_storage = InMemoryTelemetryStorage ()
2480+ telemetry_producer = TelemetryStorageProducer (telemetry_storage )
2481+ telemetry_runtime_producer = telemetry_producer .get_telemetry_runtime_producer ()
2482+ telemetry_evaluation_producer = telemetry_producer .get_telemetry_evaluation_producer ()
2483+
2484+ storages = {
2485+ 'splits' : split_storage ,
2486+ 'segments' : segment_storage ,
2487+ 'rule_based_segments' : rb_segment_storage ,
2488+ 'impressions' : InMemoryImpressionStorage (5000 , telemetry_runtime_producer ),
2489+ 'events' : InMemoryEventStorage (5000 , telemetry_runtime_producer ),
2490+ }
2491+ impmanager = ImpressionsManager (StrategyDebugMode (), StrategyNoneMode (), telemetry_runtime_producer ) # no listener
2492+ recorder = StandardRecorder (impmanager , storages ['events' ], storages ['impressions' ], telemetry_evaluation_producer , telemetry_runtime_producer , imp_counter = ImpressionsCounter ())
2493+ events_manager = EventsManager (EventsManagerConfig (), EventsDelivery ())
2494+ internal_events_task = EventsTask (events_manager .notify_internal_event , events_queue )
2495+
2496+ # Since we are passing None as SDK_Ready event, the factory will use the Redis telemetry call, using try catch to ignore the exception.
2497+ try :
2498+ factory = SplitFactory ('some_api_key' ,
2499+ storages ,
2500+ True ,
2501+ recorder ,
2502+ events_queue ,
2503+ events_manager ,
2504+ None ,
2505+ telemetry_producer = telemetry_producer ,
2506+ telemetry_init_producer = telemetry_producer .get_telemetry_init_producer (),
2507+ fallback_treatment_calculator = FallbackTreatmentCalculator (FallbackTreatmentsConfiguration (None , {'fallback_feature' : FallbackTreatment ("on-local" , '{"prop": "val"}' )}))
2508+ ) # pylint:disable=attribute-defined-outside-init
2509+ internal_events_task .start ()
2510+ except :
2511+ pass
2512+
2513+ client = factory .client ()
2514+ client .on (SdkEvent .SDK_READY , self ._ready_callback )
2515+ factory .block_until_ready (5 )
2516+ assert self .ready_flag
2517+
2518+ """Shut down the factory."""
2519+ event = threading .Event ()
2520+ factory .destroy (event )
2521+ event .wait ()
2522+
2523+ def test_sdk_ready_fire_later (self ):
2524+ """Prepare storages with test data."""
2525+ events_queue = queue .Queue ()
2526+ split_storage = InMemorySplitStorage (events_queue )
2527+ segment_storage = InMemorySegmentStorage (events_queue )
2528+ rb_segment_storage = InMemoryRuleBasedSegmentStorage (events_queue )
2529+
2530+ split_fn = os .path .join (os .path .dirname (__file__ ), 'files' , 'splitChanges.json' )
2531+ with open (split_fn , 'r' ) as flo :
2532+ data = json .loads (flo .read ())
2533+ for split in data ['ff' ]['d' ]:
2534+ split_storage .update ([splits .from_raw (split )], [], 0 )
2535+
2536+ for rbs in data ['rbs' ]['d' ]:
2537+ rb_segment_storage .update ([rule_based_segments .from_raw (rbs )], [], 0 )
2538+
2539+ segment_fn = os .path .join (os .path .dirname (__file__ ), 'files' , 'segmentEmployeesChanges.json' )
2540+ with open (segment_fn , 'r' ) as flo :
2541+ data = json .loads (flo .read ())
2542+ segment_storage .put (segments .from_raw (data ))
2543+
2544+ segment_fn = os .path .join (os .path .dirname (__file__ ), 'files' , 'segmentHumanBeignsChanges.json' )
2545+ with open (segment_fn , 'r' ) as flo :
2546+ data = json .loads (flo .read ())
2547+ segment_storage .put (segments .from_raw (data ))
2548+
2549+ telemetry_storage = InMemoryTelemetryStorage ()
2550+ telemetry_producer = TelemetryStorageProducer (telemetry_storage )
2551+ telemetry_runtime_producer = telemetry_producer .get_telemetry_runtime_producer ()
2552+ telemetry_evaluation_producer = telemetry_producer .get_telemetry_evaluation_producer ()
2553+
2554+ storages = {
2555+ 'splits' : split_storage ,
2556+ 'segments' : segment_storage ,
2557+ 'rule_based_segments' : rb_segment_storage ,
2558+ 'impressions' : InMemoryImpressionStorage (5000 , telemetry_runtime_producer ),
2559+ 'events' : InMemoryEventStorage (5000 , telemetry_runtime_producer ),
2560+ }
2561+ impmanager = ImpressionsManager (StrategyDebugMode (), StrategyNoneMode (), telemetry_runtime_producer ) # no listener
2562+ recorder = StandardRecorder (impmanager , storages ['events' ], storages ['impressions' ], telemetry_evaluation_producer , telemetry_runtime_producer , imp_counter = ImpressionsCounter ())
2563+ events_manager = EventsManager (EventsManagerConfig (), EventsDelivery ())
2564+ internal_events_task = EventsTask (events_manager .notify_internal_event , events_queue )
2565+
2566+ # Since we are passing None as SDK_Ready event, the factory will use the Redis telemetry call, using try catch to ignore the exception.
2567+ try :
2568+ factory = SplitFactory ('some_api_key' ,
2569+ storages ,
2570+ True ,
2571+ recorder ,
2572+ events_queue ,
2573+ events_manager ,
2574+ None ,
2575+ telemetry_producer = telemetry_producer ,
2576+ telemetry_init_producer = telemetry_producer .get_telemetry_init_producer (),
2577+ fallback_treatment_calculator = FallbackTreatmentCalculator (FallbackTreatmentsConfiguration (None , {'fallback_feature' : FallbackTreatment ("on-local" , '{"prop": "val"}' )}))
2578+ ) # pylint:disable=attribute-defined-outside-init
2579+ internal_events_task .start ()
2580+ except :
2581+ pass
2582+
2583+ client = factory .client ()
2584+ factory .block_until_ready (5 )
2585+
2586+ assert client .get_treatment ('user1' , 'sample_feature' , evaluation_options = EvaluationOptions ({"prop" : "value" })) == 'on'
2587+
2588+ self .ready_flag = False
2589+ client .on (SdkEvent .SDK_READY , self ._ready_callback )
2590+ assert self .ready_flag
2591+
2592+ """Shut down the factory."""
2593+ event = threading .Event ()
2594+ factory .destroy (event )
2595+ event .wait ()
2596+
2597+ def _ready_callback (self , metadata ):
2598+ self .ready_flag = True
2599+
2600+ def _timeout_callback (self , metadata ):
2601+ self .timeout_flag = True
2602+
24272603class InMemoryIntegrationAsyncTests (object ):
24282604 """Inmemory storage-based integration tests."""
24292605
@@ -4984,4 +5160,4 @@ async def _manager_methods_async(factory, skip_rbs=False):
49845160 return
49855161
49865162 assert len (await manager .split_names ()) == 9
4987- assert len (await manager .splits ()) == 9
5163+ assert len (await manager .splits ()) == 9
0 commit comments