Skip to content

Commit a5aa01d

Browse files
authored
Merge pull request #608 from splitio/FME-12219-sdk-events-models
added models, events config data and events metadata
2 parents 09e8b45 + e019bb3 commit a5aa01d

File tree

6 files changed

+234
-1
lines changed

6 files changed

+234
-1
lines changed

splitio/events/__init__.py

Whitespace-only changes.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
"""Events Manager Configuration."""
2+
from splitio.models.events import SdkEvent, SdkInternalEvent
3+
4+
class EventsManagerConfig(object):
5+
"""Events Manager Configurations class."""
6+
7+
def __init__(self):
8+
"""
9+
Construct Events Manager Configuration instance.
10+
"""
11+
self._require_all = self._get_require_all()
12+
self._prerequisites = self._get_prerequisites()
13+
self._require_any = self._get_require_any()
14+
self._suppressed_by = self._get_suppressed_by()
15+
self._execution_limits = self._get_execution_limits()
16+
self._evaluation_order = self._get_sorted_events()
17+
18+
@property
19+
def require_all(self):
20+
"""Return require all dict"""
21+
return self._require_all
22+
23+
@property
24+
def prerequisites(self):
25+
"""Return prerequisites dict"""
26+
return self._prerequisites
27+
28+
@property
29+
def require_any(self):
30+
"""Return require_any dict"""
31+
return self._require_any
32+
33+
@property
34+
def suppressed_by(self):
35+
"""Return suppressed_by dict"""
36+
return self._suppressed_by
37+
38+
@property
39+
def execution_limits(self):
40+
"""Return execution_limits dict"""
41+
return self._execution_limits
42+
43+
@property
44+
def evaluation_order(self):
45+
"""Return evaluation_order dict"""
46+
return self._evaluation_order
47+
48+
def _get_require_all(self):
49+
"""Return require all dict"""
50+
return {
51+
SdkEvent.SDK_READY: {SdkInternalEvent.SDK_READY}
52+
}
53+
54+
def _get_prerequisites(self):
55+
"""Return prerequisites dict"""
56+
return {
57+
SdkEvent.SDK_UPDATE: {SdkEvent.SDK_READY}
58+
}
59+
60+
def _get_require_any(self):
61+
"""Return require_any dict"""
62+
return {
63+
SdkEvent.SDK_UPDATE: {SdkInternalEvent.FLAG_KILLED_NOTIFICATION, SdkInternalEvent.FLAGS_UPDATED,
64+
SdkInternalEvent.RB_SEGMENTS_UPDATED, SdkInternalEvent.SEGMENTS_UPDATED},
65+
SdkEvent.SDK_READY_TIMED_OUT: {SdkInternalEvent.SDK_TIMED_OUT}
66+
}
67+
68+
def _get_suppressed_by(self):
69+
"""Return suppressed_by dict"""
70+
return {
71+
SdkEvent.SDK_READY_TIMED_OUT: {SdkEvent.SDK_READY}
72+
}
73+
74+
def _get_execution_limits(self):
75+
"""Return execution_limits dict"""
76+
return {
77+
SdkEvent.SDK_READY: 1,
78+
SdkEvent.SDK_READY_TIMED_OUT: -1,
79+
SdkEvent.SDK_UPDATE: -1
80+
}
81+
82+
def _get_sorted_events(self):
83+
"""Return dorted events set"""
84+
sorted_events = []
85+
for sdk_event in [SdkEvent.SDK_READY, SdkEvent.SDK_READY_TIMED_OUT, SdkEvent.SDK_UPDATE]:
86+
sorted_events = self._dfs_recursive(sdk_event, sorted_events)
87+
88+
return sorted_events
89+
90+
91+
def _dfs_recursive(self, sdk_event, added):
92+
"""Return sorted events set based on the dependency rules"""
93+
if sdk_event in added:
94+
return added
95+
96+
for dependent_event in self._get_dependencies(sdk_event):
97+
added = self._dfs_recursive(dependent_event, added)
98+
99+
added.append(sdk_event)
100+
return added
101+
102+
def _get_dependencies(self, sdk_event):
103+
"""Return dependencies set from prerequisites and suppressed events for a given event"""
104+
dependencies = set()
105+
for prerequisites_event_name, prerequisites_event_value in self.prerequisites.items():
106+
if prerequisites_event_name == sdk_event:
107+
for prereq_event in prerequisites_event_value:
108+
dependencies.add(prereq_event)
109+
110+
for suppressed_event_name, suppressed_event_value in self.suppressed_by.items():
111+
if sdk_event in suppressed_event_value:
112+
dependencies.add(suppressed_event_name)
113+
114+
return dependencies

splitio/events/events_metadata.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""Events Metadata."""
2+
from enum import Enum
3+
4+
class SdkEventType(Enum):
5+
"""Public event types"""
6+
7+
FLAG_UPDATE = 'FLAG_UPDATE'
8+
SEGMENT_UPDATE = 'SEGMENT_UPDATE'
9+
10+
class EventsMetadata(object):
11+
"""Events Metadata class."""
12+
13+
def __init__(self, type, names):
14+
"""
15+
Construct Events Metadata instance.
16+
"""
17+
self._type = type
18+
self._names = self._sanitize(names)
19+
20+
def get_type(self):
21+
"""Return type"""
22+
return self._type
23+
24+
def get_names(self):
25+
"""Return names"""
26+
return self._names
27+
28+
def _sanitize(self, names):
29+
"""Return sanitized names list with values str"""
30+
santized_data = set()
31+
for name in names:
32+
if isinstance(name, str):
33+
santized_data.add(name)
34+
35+
return santized_data

splitio/models/events.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
The dto is implemented as a namedtuple for performance matters.
55
"""
66
from collections import namedtuple
7-
7+
from enum import Enum
88

99
Event = namedtuple('Event', [
1010
'key',
@@ -19,3 +19,23 @@
1919
'event',
2020
'size',
2121
])
22+
23+
class SdkEvent(Enum):
24+
"""Public SDK events"""
25+
26+
SDK_READY = 'SDK_READY'
27+
SDK_READY_TIMED_OUT = 'SDK_READY_TIMED_OUT'
28+
SDK_UPDATE = 'SDK_UPDATE'
29+
30+
class SdkInternalEvent(Enum):
31+
"""Internal SDK events"""
32+
33+
SDK_READY = 'SDK_READY'
34+
SDK_TIMED_OUT = 'SDK_TIMED_OUT'
35+
FLAGS_UPDATED = 'FLAGS_UPDATED'
36+
FLAG_KILLED_NOTIFICATION = 'FLAG_KILLED_NOTIFICATION'
37+
SEGMENTS_UPDATED = 'SEGMENTS_UPDATED'
38+
RB_SEGMENTS_UPDATED = 'RB_SEGMENTS_UPDATED'
39+
LARGE_SEGMENTS_UPDATED = 'LARGE_SEGMENTS_UPDATED'
40+
41+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""EventsManagerConfig test module."""
2+
import pytest
3+
4+
from splitio.events.events_manager_config import EventsManagerConfig
5+
from splitio.models.events import SdkEvent, SdkInternalEvent
6+
7+
class EventsManagerConfigTests(object):
8+
"""Tests for EventsManagerConfig."""
9+
10+
def test_build_instance(self):
11+
config = EventsManagerConfig()
12+
13+
assert len(config.require_all[SdkEvent.SDK_READY]) == 1
14+
assert SdkInternalEvent.SDK_READY in config.require_all[SdkEvent.SDK_READY]
15+
16+
assert SdkEvent.SDK_READY in config.prerequisites[SdkEvent.SDK_UPDATE]
17+
18+
assert config.execution_limits[SdkEvent.SDK_READY_TIMED_OUT] == -1
19+
assert config.execution_limits[SdkEvent.SDK_UPDATE] == -1
20+
assert config.execution_limits[SdkEvent.SDK_READY] == 1
21+
22+
assert len(config.require_any[SdkEvent.SDK_READY_TIMED_OUT]) == 1
23+
assert SdkInternalEvent.SDK_TIMED_OUT in config.require_any[SdkEvent.SDK_READY_TIMED_OUT]
24+
25+
assert len(config.require_any[SdkEvent.SDK_UPDATE]) == 4
26+
assert SdkInternalEvent.FLAG_KILLED_NOTIFICATION in config.require_any[SdkEvent.SDK_UPDATE]
27+
assert SdkInternalEvent.FLAGS_UPDATED in config.require_any[SdkEvent.SDK_UPDATE]
28+
assert SdkInternalEvent.RB_SEGMENTS_UPDATED in config.require_any[SdkEvent.SDK_UPDATE]
29+
assert SdkInternalEvent.SEGMENTS_UPDATED in config.require_any[SdkEvent.SDK_UPDATE]
30+
31+
assert len(config.suppressed_by[SdkEvent.SDK_READY_TIMED_OUT]) == 1
32+
assert SdkEvent.SDK_READY in config.suppressed_by[SdkEvent.SDK_READY_TIMED_OUT]
33+
34+
order = 0
35+
assert len(config.evaluation_order) == 3
36+
for sdk_event in config.evaluation_order:
37+
order += 1
38+
if order == 1:
39+
assert sdk_event == SdkEvent.SDK_READY_TIMED_OUT
40+
if order == 2:
41+
assert sdk_event == SdkEvent.SDK_READY
42+
if order == 3:
43+
assert sdk_event == SdkEvent.SDK_UPDATE
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""EventsMetadata test module."""
2+
import pytest
3+
4+
from splitio.events.events_metadata import EventsMetadata
5+
from splitio.events.events_metadata import SdkEventType
6+
7+
class EventsMetadataTests(object):
8+
"""Tests for EventsMetadata."""
9+
10+
def test_build_instance(self):
11+
metadata = EventsMetadata(SdkEventType.FLAG_UPDATE, { "feature1" })
12+
assert len(metadata.get_names()) == 1
13+
assert metadata.get_names().pop() == "feature1"
14+
assert len(metadata.get_names()) == 0
15+
assert metadata.get_type() == SdkEventType.FLAG_UPDATE
16+
17+
def test_sanitize_none_input(self):
18+
metadata = EventsMetadata(SdkEventType.FLAG_UPDATE, { "feature1", None, 123, False })
19+
assert len(metadata.get_names()) == 1
20+
assert metadata.get_names().pop() == "feature1"
21+
assert len(metadata.get_names()) == 0

0 commit comments

Comments
 (0)