Skip to content
This repository was archived by the owner on Nov 8, 2024. It is now read-only.

Commit 8462d04

Browse files
feat: [add ability to export configurations] (FF-2472) (#57)
* feat: [add ability to export configurations] (FF-2472) * bump to 3.3.0 * lint * sigh
1 parent 102bd6f commit 8462d04

File tree

7 files changed

+52
-1
lines changed

7 files changed

+52
-1
lines changed

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,28 @@ class SegmentAssignmentLogger(AssignmentLogger):
103103
client_config = Config(api_key="<SDK-KEY-FROM-DASHBOARD>", assignment_logger=SegmentAssignmentLogger())
104104
```
105105

106+
## Export configuration
107+
108+
To support the use-case of needing to bootstrap a front-end client, the Eppo SDK provides a function to export flag configurations to a JSON string.
109+
110+
Use the `get_flag_configurations` function to export flag configurations to a JSON string and then send it to the front-end client.
111+
112+
```python
113+
from fastapi import JSONResponse
114+
115+
import eppo_client
116+
import json
117+
118+
client = eppo_client.get_instance()
119+
flag_configurations = client.get_flag_configurations()
120+
121+
# Convert flag configurations to a JSON string
122+
flag_config_json = json.dumps(flag_configurations)
123+
124+
# Create a JSONResponse object with the stringified JSON
125+
response = JSONResponse(content={"flagConfigurations": flag_config_json})
126+
```
127+
106128
## Philosophy
107129

108130
Eppo's SDKs are built for simplicity, speed and reliability. Flag configurations are compressed and distributed over a global CDN (Fastly), typically reaching your servers in under 15ms. Server SDKs continue polling Eppo’s API at 30-second intervals. Configurations are then cached locally, ensuring that each assignment is made instantly. Evaluation logic within each SDK consists of a few lines of simple numeric and string comparisons. The typed functions listed above are all developers need to understand, abstracting away the complexity of the Eppo's underlying (and expanding) feature set.

eppo_client/client.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
ContextAttributes,
1111
ActionContexts,
1212
)
13+
from eppo_client.models import Flag
1314
from eppo_client.configuration_requestor import (
1415
ExperimentConfigurationRequestor,
1516
)
@@ -386,6 +387,13 @@ def get_flag_keys(self):
386387
"""
387388
return self.__config_requestor.get_flag_keys()
388389

390+
def get_flag_configurations(self) -> Dict[str, Flag]:
391+
"""
392+
Returns a dictionary of all flag configurations that have been initialized.
393+
This can be useful to debug the initialization process or to bootstrap a front-end client.
394+
"""
395+
return self.__config_requestor.get_flag_configurations()
396+
389397
def get_bandit_keys(self):
390398
"""
391399
Returns a list of all bandit keys that have been initialized.

eppo_client/configuration_requestor.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ def get_bandit_model(self, bandit_key: str) -> Optional[BanditData]:
3636
def get_flag_keys(self):
3737
return self.__flag_config_store.get_keys()
3838

39+
def get_flag_configurations(self):
40+
return self.__flag_config_store.get_configurations()
41+
3942
def get_bandit_keys(self):
4043
return self.__bandit_config_store.get_keys()
4144

eppo_client/configuration_store.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ def set_configurations(self, configs: Dict[str, T]):
2121
def get_keys(self):
2222
with self.__lock.reader():
2323
return set(self.__cache.keys())
24+
25+
def get_configurations(self):
26+
with self.__lock.reader():
27+
return self.__cache

eppo_client/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "3.2.1"
1+
__version__ = "3.3.0"

test/client_test.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,13 @@ def test_client_has_flags():
218218
assert len(client.get_flag_keys()) > 0, "No flags have been loaded by the client"
219219

220220

221+
def test_client_flag_configurations():
222+
client = get_instance()
223+
assert (
224+
len(client.get_flag_configurations()) > 0
225+
), "No flags have been loaded by the client"
226+
227+
221228
@pytest.mark.parametrize("test_case", test_data)
222229
def test_assign_subject_in_sample(test_case):
223230
client = get_instance()

test/configuration_store_test.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ def test_get_keys():
3434
assert len(keys) == 2
3535

3636

37+
def test_get_configurations():
38+
config = {"flag1": mock_flag, "flag2": mock_flag}
39+
store.set_configurations(config)
40+
configurations = store.get_configurations()
41+
assert configurations == config
42+
43+
3744
def test_evicts_old_entries_when_max_size_exceeded():
3845
store.set_configurations({"item_to_be_evicted": mock_flag})
3946
assert store.get_configuration("item_to_be_evicted") == mock_flag

0 commit comments

Comments
 (0)