Skip to content

Commit a396266

Browse files
committed
added EventStorage class with tests
1 parent 44de46c commit a396266

2 files changed

Lines changed: 153 additions & 3 deletions

File tree

splitio/storage/pluggable.py

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from splitio.models import splits, segments
77
from splitio.models.impressions import Impression
8-
from splitio.storage import SplitStorage, SegmentStorage, ImpressionStorage
8+
from splitio.storage import SplitStorage, SegmentStorage, ImpressionStorage, EventStorage
99

1010
_LOGGER = logging.getLogger(__name__)
1111

@@ -556,3 +556,76 @@ def clear(self):
556556
Clear data.
557557
"""
558558
raise NotImplementedError('Only consumer mode is supported.')
559+
560+
561+
class PluggableEventsStorage(EventStorage):
562+
"""Redis based event storage class."""
563+
564+
def __init__(self, pluggable_adapter, sdk_metadata, prefix=None):
565+
"""
566+
Class constructor.
567+
568+
:param redis_client: Redis client or compliant interface.
569+
:type redis_client: splitio.storage.adapters.redis.RedisAdapter
570+
:param sdk_metadata: SDK & Machine information.
571+
:type sdk_metadata: splitio.client.util.SdkMetadata
572+
"""
573+
self._pluggable_adapter = pluggable_adapter
574+
self._sdk_metadata = {
575+
's': sdk_metadata.sdk_version,
576+
'n': sdk_metadata.instance_name,
577+
'i': sdk_metadata.instance_ip,
578+
}
579+
self._events_queue_key = 'SPLITIO.events'
580+
if prefix is not None:
581+
self._events_queue_key = prefix + "." + self._events_queue_key
582+
583+
def _wrap_events(self, events):
584+
return [
585+
json.dumps({
586+
'e': {
587+
'key': e.event.key,
588+
'trafficTypeName': e.event.traffic_type_name,
589+
'eventTypeId': e.event.event_type_id,
590+
'value': e.event.value,
591+
'timestamp': e.event.timestamp,
592+
'properties': e.event.properties,
593+
},
594+
'm': self._sdk_metadata
595+
})
596+
for e in events
597+
]
598+
599+
def put(self, events):
600+
"""
601+
Add an event to the redis storage.
602+
603+
:param event: Event to add to the queue.
604+
:type event: splitio.models.events.Event
605+
606+
:return: Whether the event has been added or not.
607+
:rtype: bool
608+
"""
609+
to_store = self._wrap_events(events)
610+
try:
611+
self._pluggable_adapter.push_items(self._events_queue_key, *to_store)
612+
return True
613+
except Exception:
614+
_LOGGER.error('Something went wrong when trying to add event to redis')
615+
_LOGGER.debug('Error: ', exc_info=True)
616+
return False
617+
618+
def pop_many(self, count):
619+
"""
620+
Pop the oldest N events from storage.
621+
622+
:param count: Number of events to pop.
623+
:type count: int
624+
"""
625+
raise NotImplementedError('Only redis-consumer mode is supported.')
626+
627+
def clear(self):
628+
"""
629+
Clear data.
630+
"""
631+
raise NotImplementedError('Not supported for redis.')

tests/storage/test_pluggable.py

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
from splitio.models import splits, segments
66
from splitio.models.segments import Segment
77
from splitio.models.impressions import Impression
8-
from splitio.storage.pluggable import PluggableSplitStorage, PluggableSegmentStorage, PluggableImpressionsStorage
8+
from splitio.models.events import Event, EventWrapper
9+
from splitio.storage.pluggable import PluggableSplitStorage, PluggableSegmentStorage, PluggableImpressionsStorage, PluggableEventsStorage
910
from splitio.client.util import get_metadata, SdkMetadata
1011

1112
from tests.integration import splits_json
@@ -403,4 +404,80 @@ def test_wrap_impressions(self):
403404
'm': 321654,
404405
}
405406
})
406-
])
407+
])
408+
409+
class PluggableEventsStorageTests(object):
410+
"""In memory events storage test cases."""
411+
412+
def setup_method(self):
413+
"""Prepare storages with test data."""
414+
self.mock_adapter = StorageMockAdapter()
415+
self.metadata = SdkMetadata('python-1.1.1', 'hostname', 'ip')
416+
self.pluggable_events_storage = PluggableEventsStorage(self.mock_adapter, self.metadata, 'myprefix')
417+
418+
def test_init(self):
419+
assert(self.pluggable_events_storage._events_queue_key == "myprefix.SPLITIO.events")
420+
assert(self.pluggable_events_storage._sdk_metadata == {
421+
's': self.metadata.sdk_version,
422+
'n': self.metadata.instance_name,
423+
'i': self.metadata.instance_ip,
424+
})
425+
426+
pluggable2 = PluggableEventsStorage(self.mock_adapter, self.metadata)
427+
assert(pluggable2._events_queue_key == "SPLITIO.events")
428+
429+
def test_put(self):
430+
events = [
431+
EventWrapper(event=Event('key1', 'user', 'purchase', 10, 123456, None), size=32768),
432+
EventWrapper(event=Event('key2', 'user', 'purchase', 10, 123456, None), size=32768),
433+
EventWrapper(event=Event('key3', 'user', 'purchase', 10, 123456, None), size=32768),
434+
EventWrapper(event=Event('key4', 'user', 'purchase', 10, 123456, None), size=32768),
435+
]
436+
self.pluggable_events_storage.put(events)
437+
assert(self.pluggable_events_storage._events_queue_key in self.mock_adapter._keys)
438+
assert(self.mock_adapter._keys["myprefix.SPLITIO.events"] == self.pluggable_events_storage._wrap_events(events))
439+
440+
events2 = [
441+
EventWrapper(event=Event('key5', 'user', 'purchase', 10, 123456, None), size=32768),
442+
EventWrapper(event=Event('key6', 'user', 'purchase', 10, 123456, None), size=32768),
443+
]
444+
self.pluggable_events_storage.put(events2)
445+
assert(self.mock_adapter._keys["myprefix.SPLITIO.events"] == self.pluggable_events_storage._wrap_events(events + events2))
446+
447+
def test_wrap_events(self):
448+
events = [
449+
EventWrapper(event=Event('key1', 'user', 'purchase', 10, 123456, None), size=32768),
450+
EventWrapper(event=Event('key2', 'user', 'purchase', 10, 123456, None), size=32768),
451+
]
452+
assert(self.pluggable_events_storage._wrap_events(events) == [
453+
json.dumps({
454+
'e': {
455+
'key': 'key1',
456+
'trafficTypeName': 'user',
457+
'eventTypeId': 'purchase',
458+
'value': 10,
459+
'timestamp': 123456,
460+
'properties': None,
461+
},
462+
'm': {
463+
's': self.metadata.sdk_version,
464+
'n': self.metadata.instance_name,
465+
'i': self.metadata.instance_ip,
466+
}
467+
}),
468+
json.dumps({
469+
'e': {
470+
'key': 'key2',
471+
'trafficTypeName': 'user',
472+
'eventTypeId': 'purchase',
473+
'value': 10,
474+
'timestamp': 123456,
475+
'properties': None,
476+
},
477+
'm': {
478+
's': self.metadata.sdk_version,
479+
'n': self.metadata.instance_name,
480+
'i': self.metadata.instance_ip,
481+
}
482+
})
483+
])

0 commit comments

Comments
 (0)