Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added splitio/events/__init__.py
Empty file.
124 changes: 124 additions & 0 deletions splitio/events/events_manager_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
"""Events Manager Configuration."""
from splitio.models.events import SdkEvent, SdkInternalEvent

class EventsManagerConfig(object):
"""Events Manager Configurations class."""

def __init__(self):
"""
Construct Events Manager Configuration instance.
"""
self._require_all = self._get_require_all()
self._prerequisites = self._get_prerequisites()
self._require_any = self._get_require_any()
self._suppressed_by = self._get_suppressed_by()
self._execution_limits = self._get_execution_limits()
self._evaluation_order = self._get_sorted_events()

@property
def require_all(self):
"""Return require all dict"""
return self._require_all

@property
def prerequisites(self):
"""Return prerequisites dict"""
return self._prerequisites

@property
def require_any(self):
"""Return require_any dict"""
return self._require_any

@property
def suppressed_by(self):
"""Return suppressed_by dict"""
return self._suppressed_by

@property
def execution_limits(self):
"""Return execution_limits dict"""
return self._execution_limits

@property
def prerequisites(self):
"""Return require all dict"""
return self._prerequisites

@property
def evaluation_order(self):
"""Return evaluation_order dict"""
return self._evaluation_order

@property
def sorted_events(self):
"""Return sorted_events dict"""
return self._sorted_events

def _get_require_all(self):
"""Return require all dict"""
return {
SdkEvent.SDK_READY: {SdkInternalEvent.SDK_READY}
}

def _get_prerequisites(self):
"""Return prerequisites dict"""
return {
SdkEvent.SDK_UPDATE: {SdkEvent.SDK_READY}
}

def _get_require_any(self):
"""Return require_any dict"""
return {
SdkEvent.SDK_UPDATE: {SdkInternalEvent.FLAG_KILLED_NOTIFICATION, SdkInternalEvent.FLAGS_UPDATED,
SdkInternalEvent.RB_SEGMENTS_UPDATED, SdkInternalEvent.SEGMENTS_UPDATED},
SdkEvent.SDK_READY_TIMED_OUT: {SdkInternalEvent.SDK_TIMED_OUT}
}

def _get_suppressed_by(self):
"""Return suppressed_by dict"""
return {
SdkEvent.SDK_READY_TIMED_OUT: {SdkEvent.SDK_READY}
}

def _get_execution_limits(self):
"""Return execution_limits dict"""
return {
SdkEvent.SDK_READY: 1,
SdkEvent.SDK_READY_TIMED_OUT: -1,
SdkEvent.SDK_UPDATE: -1
}

def _get_sorted_events(self):
"""Return dorted events set"""
sorted_events = []
for sdk_event in [SdkEvent.SDK_READY, SdkEvent.SDK_READY_TIMED_OUT, SdkEvent.SDK_UPDATE]:
sorted_events = self._dfs_recursive(sdk_event, sorted_events)

return sorted_events


def _dfs_recursive(self, sdk_event, added):
"""Return sorted events set based on the dependency rules"""
if sdk_event in added:
return added

for dependent_event in self._get_dependencies(sdk_event):
added = self._dfs_recursive(dependent_event, added)

added.append(sdk_event)
return added

def _get_dependencies(self, sdk_event):
"""Return dependencies set from prerequisites and suppressed events for a given event"""
dependencies = set()
for prerequisites_event_name, prerequisites_event_value in self.prerequisites.items():
if prerequisites_event_name == sdk_event:
for prereq_event in prerequisites_event_value:
dependencies.add(prereq_event)

for suppressed_event_name, suppressed_event_value in self.suppressed_by.items():
if sdk_event in suppressed_event_value:
dependencies.add(suppressed_event_name)

return dependencies
35 changes: 35 additions & 0 deletions splitio/events/events_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Events Metadata."""
from enum import Enum

class SdkEventType(Enum):
"""Public event types"""

FLAG_UPDATE = 'FLAG_UPDATE'
SEGMENT_UPDATE = 'SEGMENT_UPDATE'

class EventsMetadata(object):
"""Events Metadata class."""

def __init__(self, type, names):
"""
Construct Events Metadata instance.
"""
self._type = type
self._names = self._sanitize(names)

def get_type(self):
"""Return type"""
return self._type

def get_names(self):
"""Return names"""
return self._names

def _sanitize(self, names):
"""Return sanitized names list with values str"""
santized_data = set()
for name in names:
if isinstance(name, str):
santized_data.add(name)

return santized_data
22 changes: 21 additions & 1 deletion splitio/models/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
The dto is implemented as a namedtuple for performance matters.
"""
from collections import namedtuple

from enum import Enum

Event = namedtuple('Event', [
'key',
Expand All @@ -19,3 +19,23 @@
'event',
'size',
])

class SdkEvent(Enum):
"""Public SDK events"""

SDK_READY = 'SDK_READY'
SDK_READY_TIMED_OUT = 'SDK_READY_TIMED_OUT'
SDK_UPDATE = 'SDK_UPDATE'

class SdkInternalEvent(Enum):
"""Internal SDK events"""

SDK_READY = 'SDK_READY'
SDK_TIMED_OUT = 'SDK_TIMED_OUT'
FLAGS_UPDATED = 'FLAGS_UPDATED'
FLAG_KILLED_NOTIFICATION = 'FLAG_KILLED_NOTIFICATION'
SEGMENTS_UPDATED = 'SEGMENTS_UPDATED'
RB_SEGMENTS_UPDATED = 'RB_SEGMENTS_UPDATED'
LARGE_SEGMENTS_UPDATED = 'LARGE_SEGMENTS_UPDATED'


43 changes: 43 additions & 0 deletions tests/events/test_events_manager_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""EventsManagerConfig test module."""
import pytest

from splitio.events.events_manager_config import EventsManagerConfig
from splitio.models.events import SdkEvent, SdkInternalEvent

class EventsManagerConfigTests(object):
"""Tests for EventsManagerConfig."""

def test_build_instance(self):
config = EventsManagerConfig()

assert len(config.require_all[SdkEvent.SDK_READY]) == 1
assert SdkInternalEvent.SDK_READY in config.require_all[SdkEvent.SDK_READY]

assert SdkEvent.SDK_READY in config.prerequisites[SdkEvent.SDK_UPDATE]

assert config.execution_limits[SdkEvent.SDK_READY_TIMED_OUT] == -1
assert config.execution_limits[SdkEvent.SDK_UPDATE] == -1
assert config.execution_limits[SdkEvent.SDK_READY] == 1

assert len(config.require_any[SdkEvent.SDK_READY_TIMED_OUT]) == 1
assert SdkInternalEvent.SDK_TIMED_OUT in config.require_any[SdkEvent.SDK_READY_TIMED_OUT]

assert len(config.require_any[SdkEvent.SDK_UPDATE]) == 4
assert SdkInternalEvent.FLAG_KILLED_NOTIFICATION in config.require_any[SdkEvent.SDK_UPDATE]
assert SdkInternalEvent.FLAGS_UPDATED in config.require_any[SdkEvent.SDK_UPDATE]
assert SdkInternalEvent.RB_SEGMENTS_UPDATED in config.require_any[SdkEvent.SDK_UPDATE]
assert SdkInternalEvent.SEGMENTS_UPDATED in config.require_any[SdkEvent.SDK_UPDATE]

assert len(config.suppressed_by[SdkEvent.SDK_READY_TIMED_OUT]) == 1
assert SdkEvent.SDK_READY in config.suppressed_by[SdkEvent.SDK_READY_TIMED_OUT]

order = 0
assert len(config.evaluation_order) == 3
for sdk_event in config.evaluation_order:
order += 1
if order == 1:
assert sdk_event == SdkEvent.SDK_READY_TIMED_OUT
if order == 2:
assert sdk_event == SdkEvent.SDK_READY
if order == 3:
assert sdk_event == SdkEvent.SDK_UPDATE
21 changes: 21 additions & 0 deletions tests/events/test_events_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""EventsMetadata test module."""
import pytest

from splitio.events.events_metadata import EventsMetadata
from splitio.events.events_metadata import SdkEventType

class EventsMetadataTests(object):
"""Tests for EventsMetadata."""

def test_build_instance(self):
metadata = EventsMetadata(SdkEventType.FLAG_UPDATE, { "feature1" })
assert len(metadata.get_names()) == 1
assert metadata.get_names().pop() == "feature1"
assert len(metadata.get_names()) == 0
assert metadata.get_type() == SdkEventType.FLAG_UPDATE

def test_sanitize_none_input(self):
metadata = EventsMetadata(SdkEventType.FLAG_UPDATE, { "feature1", None, 123, False })
assert len(metadata.get_names()) == 1
assert metadata.get_names().pop() == "feature1"
assert len(metadata.get_names()) == 0