splitio-client 10.2.0__tar.gz → 10.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- splitio_client-10.3.0/PKG-INFO +101 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/setup.py +3 -2
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/api/client.py +34 -7
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/api/commons.py +18 -2
- splitio_client-10.3.0/splitio/api/splits.py +202 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/client/client.py +2 -2
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/client/factory.py +20 -7
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/evaluator.py +104 -41
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/condition.py +6 -4
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/matchers/__init__.py +4 -1
- splitio_client-10.3.0/splitio/models/grammar/matchers/prerequisites.py +38 -0
- splitio_client-10.3.0/splitio/models/grammar/matchers/rule_based_segment.py +72 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/impressions.py +5 -0
- splitio_client-10.3.0/splitio/models/rule_based_segments.py +195 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/splits.py +45 -5
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/telemetry.py +1 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/push/parser.py +57 -3
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/push/processor.py +6 -4
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/push/workers.py +104 -30
- splitio_client-10.3.0/splitio/spec.py +1 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/storage/__init__.py +72 -1
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/storage/inmemmory.py +274 -1
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/storage/pluggable.py +283 -3
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/storage/redis.py +291 -3
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/sync/segment.py +11 -4
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/sync/split.py +245 -97
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/sync/util.py +4 -0
- splitio_client-10.3.0/splitio/util/storage_helper.py +200 -0
- splitio_client-10.3.0/splitio/version.py +1 -0
- splitio_client-10.3.0/splitio_client.egg-info/PKG-INFO +101 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio_client.egg-info/SOURCES.txt +3 -1
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio_client.egg-info/requires.txt +2 -1
- splitio_client-10.2.0/LICENSE.txt +0 -13
- splitio_client-10.2.0/PKG-INFO +0 -125
- splitio_client-10.2.0/splitio/api/splits.py +0 -121
- splitio_client-10.2.0/splitio/spec.py +0 -1
- splitio_client-10.2.0/splitio/util/storage_helper.py +0 -99
- splitio_client-10.2.0/splitio/version.py +0 -1
- splitio_client-10.2.0/splitio_client.egg-info/PKG-INFO +0 -125
- {splitio_client-10.2.0 → splitio_client-10.3.0}/README.md +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/setup.cfg +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/api/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/api/auth.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/api/events.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/api/impressions.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/api/segments.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/api/telemetry.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/client/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/client/config.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/client/input_validator.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/client/key.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/client/listener.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/client/localhost.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/client/manager.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/client/util.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/cache/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/cache/lru.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/filters.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/hashfns/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/hashfns/legacy.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/hashfns/murmur3py.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/impressions/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/impressions/adapters.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/impressions/impressions.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/impressions/manager.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/impressions/strategies.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/impressions/unique_keys_tracker.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/splitters.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/engine/telemetry.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/exceptions.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/factories.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/impressions.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/key.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/datatypes.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/events.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/matchers/base.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/matchers/keys.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/matchers/misc.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/matchers/numeric.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/matchers/semver.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/matchers/sets.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/matchers/string.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/matchers/utils/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/matchers/utils/utils.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/grammar/partitions.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/notification.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/segments.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/models/token.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/optional/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/optional/loaders.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/push/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/push/manager.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/push/splitsse.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/push/sse.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/push/status_tracker.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/recorder/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/recorder/recorder.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/storage/adapters/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/storage/adapters/cache_trait.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/storage/adapters/redis.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/storage/adapters/util.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/sync/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/sync/event.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/sync/impression.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/sync/manager.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/sync/synchronizer.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/sync/telemetry.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/sync/unique_keys.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/tasks/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/tasks/events_sync.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/tasks/impressions_sync.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/tasks/segment_sync.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/tasks/split_sync.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/tasks/telemetry_sync.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/tasks/unique_keys_sync.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/tasks/util/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/tasks/util/asynctask.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/tasks/util/workerpool.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/util/__init__.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/util/backoff.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/util/decorators.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/util/threadutil.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio/util/time.py +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio_client.egg-info/dependency_links.txt +0 -0
- {splitio_client-10.2.0 → splitio_client-10.3.0}/splitio_client.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: splitio_client
|
|
3
|
+
Version: 10.3.0
|
|
4
|
+
Summary: Split.io Python Client
|
|
5
|
+
Home-page: https://github.com/splitio/python-client
|
|
6
|
+
Author: Patricio Echague, Sebastian Arrubia
|
|
7
|
+
Author-email: pato@split.io, sebastian@split.io
|
|
8
|
+
License: Apache License 2.0
|
|
9
|
+
Download-URL: https://github.com/splitio/python-client/tarball/10.3.0
|
|
10
|
+
Description: # Split Python SDK
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
## Overview
|
|
14
|
+
This SDK is designed to work with Split, the platform for controlled rollouts, which serves features to your users via a Split feature flag to manage your complete customer experience.
|
|
15
|
+
|
|
16
|
+
[](https://twitter.com/intent/follow?screen_name=splitsoftware)
|
|
17
|
+
|
|
18
|
+
## Compatibility
|
|
19
|
+
This SDK is compatible with **Python 3.7 and higher**.
|
|
20
|
+
|
|
21
|
+
## Getting started
|
|
22
|
+
Below is a simple example that describes the instantiation and most basic usage of our SDK:
|
|
23
|
+
|
|
24
|
+
Run `pip install splitio_client`
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from splitio import get_factory
|
|
29
|
+
from splitio.exceptions import TimeoutException
|
|
30
|
+
factory = get_factory('YOUR_SDK_TYPE_API_KEY', config=config)
|
|
31
|
+
try:
|
|
32
|
+
factory.block_until_ready(5) # wait up to 5 seconds
|
|
33
|
+
split = factory.client()
|
|
34
|
+
treatment = split.get_treatment('CUSTOMER_ID', 'FEATURE_FLAG_NAME')
|
|
35
|
+
if treatment == "on":
|
|
36
|
+
# insert code here to show on treatment
|
|
37
|
+
elif treatment == "off":
|
|
38
|
+
# insert code here to show off treatment
|
|
39
|
+
else:
|
|
40
|
+
# insert your control treatment code here
|
|
41
|
+
except TimeoutException:
|
|
42
|
+
# Now the user can choose whether to abort the whole execution, or just keep going
|
|
43
|
+
# without a ready client, which if configured properly, should become ready at some point.
|
|
44
|
+
pass
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Please refer to [our official docs](https://help.split.io/hc/en-us/articles/360020359652-Python-SDK) to learn about all the functionality provided by our SDK and the configuration options available for tailoring it to your current application setup.
|
|
48
|
+
|
|
49
|
+
## Submitting issues
|
|
50
|
+
The Split team monitors all issues submitted to this [issue tracker](https://github.com/splitio/python-client/issues). We encourage you to use this issue tracker to submit any bug reports, feedback, and feature enhancements. We'll do our best to respond in a timely manner.
|
|
51
|
+
|
|
52
|
+
## Contributing
|
|
53
|
+
Please see [Contributors Guide](CONTRIBUTORS-GUIDE.md) to find all you need to submit a Pull Request (PR).
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
Licensed under the Apache License, Version 2.0. See: [Apache License](http://www.apache.org/licenses/).
|
|
57
|
+
|
|
58
|
+
## About Split
|
|
59
|
+
|
|
60
|
+
Split is the leading Feature Delivery Platform for engineering teams that want to confidently deploy features as fast as they can develop them. Split’s fine-grained management, real-time monitoring, and data-driven experimentation ensure that new features will improve the customer experience without breaking or degrading performance. Companies like Twilio, Salesforce, GoDaddy and WePay trust Split to power their feature delivery.
|
|
61
|
+
|
|
62
|
+
To learn more about Split, contact hello@split.io, or get started with feature flags for free at https://www.split.io/signup.
|
|
63
|
+
|
|
64
|
+
Split has built and maintains SDKs for:
|
|
65
|
+
|
|
66
|
+
* .NET [Github](https://github.com/splitio/dotnet-client) [Docs](https://help.split.io/hc/en-us/articles/360020240172--NET-SDK)
|
|
67
|
+
* Android [Github](https://github.com/splitio/android-client) [Docs](https://help.split.io/hc/en-us/articles/360020343291-Android-SDK)
|
|
68
|
+
* Angular [Github](https://github.com/splitio/angular-sdk-plugin) [Docs](https://help.split.io/hc/en-us/articles/6495326064397-Angular-utilities)
|
|
69
|
+
* GO [Github](https://github.com/splitio/go-client) [Docs](https://help.split.io/hc/en-us/articles/360020093652-Go-SDK)
|
|
70
|
+
* iOS [Github](https://github.com/splitio/ios-client) [Docs](https://help.split.io/hc/en-us/articles/360020401491-iOS-SDK)
|
|
71
|
+
* Java [Github](https://github.com/splitio/java-client) [Docs](https://help.split.io/hc/en-us/articles/360020405151-Java-SDK)
|
|
72
|
+
* JavaScript [Github](https://github.com/splitio/javascript-client) [Docs](https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK)
|
|
73
|
+
* JavaScript for Browser [Github](https://github.com/splitio/javascript-browser-client) [Docs](https://help.split.io/hc/en-us/articles/360058730852-Browser-SDK)
|
|
74
|
+
* Node [Github](https://github.com/splitio/javascript-client) [Docs](https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK)
|
|
75
|
+
* PHP [Github](https://github.com/splitio/php-client) [Docs](https://help.split.io/hc/en-us/articles/360020350372-PHP-SDK)
|
|
76
|
+
* Python [Github](https://github.com/splitio/python-client) [Docs](https://help.split.io/hc/en-us/articles/360020359652-Python-SDK)
|
|
77
|
+
* React [Github](https://github.com/splitio/react-client) [Docs](https://help.split.io/hc/en-us/articles/360038825091-React-SDK)
|
|
78
|
+
* React Native [Github](https://github.com/splitio/react-native-client) [Docs](https://help.split.io/hc/en-us/articles/4406066357901-React-Native-SDK)
|
|
79
|
+
* Redux [Github](https://github.com/splitio/redux-client) [Docs](https://help.split.io/hc/en-us/articles/360038851551-Redux-SDK)
|
|
80
|
+
* Ruby [Github](https://github.com/splitio/ruby-client) [Docs](https://help.split.io/hc/en-us/articles/360020673251-Ruby-SDK)
|
|
81
|
+
|
|
82
|
+
For a comprehensive list of open source projects visit our [Github page](https://github.com/splitio?utf8=%E2%9C%93&query=%20only%3Apublic%20).
|
|
83
|
+
|
|
84
|
+
**Learn more about Split:**
|
|
85
|
+
|
|
86
|
+
Visit [split.io/product](https://www.split.io/product) for an overview of Split, or visit our documentation at [help.split.io](http://help.split.io) for more detailed information.
|
|
87
|
+
|
|
88
|
+
Platform: UNKNOWN
|
|
89
|
+
Classifier: Environment :: Console
|
|
90
|
+
Classifier: Intended Audience :: Developers
|
|
91
|
+
Classifier: Programming Language :: Python
|
|
92
|
+
Classifier: Programming Language :: Python :: 2
|
|
93
|
+
Classifier: Programming Language :: Python :: 3
|
|
94
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
95
|
+
Description-Content-Type: text/markdown
|
|
96
|
+
Provides-Extra: test
|
|
97
|
+
Provides-Extra: redis
|
|
98
|
+
Provides-Extra: uwsgi
|
|
99
|
+
Provides-Extra: cpphash
|
|
100
|
+
Provides-Extra: asyncio
|
|
101
|
+
Provides-Extra: kerberos
|
|
@@ -8,7 +8,7 @@ TESTS_REQUIRES = [
|
|
|
8
8
|
'flake8',
|
|
9
9
|
'pytest==7.0.1',
|
|
10
10
|
'pytest-mock==3.11.1',
|
|
11
|
-
'coverage',
|
|
11
|
+
'coverage==7.0.0',
|
|
12
12
|
'pytest-cov==4.1.0',
|
|
13
13
|
'importlib-metadata==6.7',
|
|
14
14
|
'tomli==1.2.3',
|
|
@@ -17,7 +17,8 @@ TESTS_REQUIRES = [
|
|
|
17
17
|
'pytest-asyncio==0.21.0',
|
|
18
18
|
'aiohttp>=3.8.4',
|
|
19
19
|
'aiofiles>=23.1.0',
|
|
20
|
-
'requests-kerberos>=0.15.0'
|
|
20
|
+
'requests-kerberos>=0.15.0',
|
|
21
|
+
'urllib3==2.0.7'
|
|
21
22
|
]
|
|
22
23
|
|
|
23
24
|
INSTALL_REQUIRES = [
|
|
@@ -92,6 +92,25 @@ class HTTPAdapterWithProxyKerberosAuth(requests.adapters.HTTPAdapter):
|
|
|
92
92
|
class HttpClientBase(object, metaclass=abc.ABCMeta):
|
|
93
93
|
"""HttpClient wrapper template."""
|
|
94
94
|
|
|
95
|
+
def __init__(self, timeout=None, sdk_url=None, events_url=None, auth_url=None, telemetry_url=None):
|
|
96
|
+
"""
|
|
97
|
+
Class constructor.
|
|
98
|
+
|
|
99
|
+
:param timeout: How many milliseconds to wait until the server responds.
|
|
100
|
+
:type timeout: int
|
|
101
|
+
:param sdk_url: Optional alternative sdk URL.
|
|
102
|
+
:type sdk_url: str
|
|
103
|
+
:param events_url: Optional alternative events URL.
|
|
104
|
+
:type events_url: str
|
|
105
|
+
:param auth_url: Optional alternative auth URL.
|
|
106
|
+
:type auth_url: str
|
|
107
|
+
:param telemetry_url: Optional alternative telemetry URL.
|
|
108
|
+
:type telemetry_url: str
|
|
109
|
+
"""
|
|
110
|
+
_LOGGER.debug("Initializing httpclient")
|
|
111
|
+
self._timeout = timeout/1000 if timeout else None # Convert ms to seconds.
|
|
112
|
+
self._urls = _construct_urls(sdk_url, events_url, auth_url, telemetry_url)
|
|
113
|
+
|
|
95
114
|
@abc.abstractmethod
|
|
96
115
|
def get(self, server, path, apikey):
|
|
97
116
|
"""http get request"""
|
|
@@ -113,6 +132,9 @@ class HttpClientBase(object, metaclass=abc.ABCMeta):
|
|
|
113
132
|
self._telemetry_runtime_producer = telemetry_runtime_producer
|
|
114
133
|
self._metric_name = metric_name
|
|
115
134
|
|
|
135
|
+
def is_sdk_endpoint_overridden(self):
|
|
136
|
+
return self._urls['sdk'] != SDK_URL
|
|
137
|
+
|
|
116
138
|
def _get_headers(self, extra_headers, sdk_key):
|
|
117
139
|
headers = _build_basic_headers(sdk_key)
|
|
118
140
|
if extra_headers is not None:
|
|
@@ -154,10 +176,8 @@ class HttpClient(HttpClientBase):
|
|
|
154
176
|
:param telemetry_url: Optional alternative telemetry URL.
|
|
155
177
|
:type telemetry_url: str
|
|
156
178
|
"""
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
self._urls = _construct_urls(sdk_url, events_url, auth_url, telemetry_url)
|
|
160
|
-
|
|
179
|
+
HttpClientBase.__init__(self, timeout, sdk_url, events_url, auth_url, telemetry_url)
|
|
180
|
+
|
|
161
181
|
def get(self, server, path, sdk_key, query=None, extra_headers=None): # pylint: disable=too-many-arguments
|
|
162
182
|
"""
|
|
163
183
|
Issue a get request.
|
|
@@ -187,7 +207,11 @@ class HttpClient(HttpClientBase):
|
|
|
187
207
|
self._record_telemetry(response.status_code, get_current_epoch_time_ms() - start)
|
|
188
208
|
return HttpResponse(response.status_code, response.text, response.headers)
|
|
189
209
|
|
|
190
|
-
except
|
|
210
|
+
except requests.exceptions.ChunkedEncodingError as exc:
|
|
211
|
+
_LOGGER.error("IncompleteRead exception detected: %s", exc)
|
|
212
|
+
return HttpResponse(400, "", {})
|
|
213
|
+
|
|
214
|
+
except Exception as exc: # pylint: disable=broad-except
|
|
191
215
|
raise HttpClientException(_EXC_MSG.format(source='request')) from exc
|
|
192
216
|
|
|
193
217
|
def post(self, server, path, sdk_key, body, query=None, extra_headers=None): # pylint: disable=too-many-arguments
|
|
@@ -241,8 +265,7 @@ class HttpClientAsync(HttpClientBase):
|
|
|
241
265
|
:param telemetry_url: Optional alternative telemetry URL.
|
|
242
266
|
:type telemetry_url: str
|
|
243
267
|
"""
|
|
244
|
-
self
|
|
245
|
-
self._urls = _construct_urls(sdk_url, events_url, auth_url, telemetry_url)
|
|
268
|
+
HttpClientBase.__init__(self, timeout, sdk_url, events_url, auth_url, telemetry_url)
|
|
246
269
|
self._session = aiohttp.ClientSession()
|
|
247
270
|
|
|
248
271
|
async def get(self, server, path, apikey, query=None, extra_headers=None): # pylint: disable=too-many-arguments
|
|
@@ -281,6 +304,10 @@ class HttpClientAsync(HttpClientBase):
|
|
|
281
304
|
await self._record_telemetry(response.status, get_current_epoch_time_ms() - start)
|
|
282
305
|
return HttpResponse(response.status, body, response.headers)
|
|
283
306
|
|
|
307
|
+
except aiohttp.ClientPayloadError as exc:
|
|
308
|
+
_LOGGER.error("ContentLengthError exception detected: %s", exc)
|
|
309
|
+
return HttpResponse(400, "", {})
|
|
310
|
+
|
|
284
311
|
except aiohttp.ClientError as exc: # pylint: disable=broad-except
|
|
285
312
|
raise HttpClientException(_EXC_MSG.format(source='aiohttp')) from exc
|
|
286
313
|
|
|
@@ -57,7 +57,7 @@ def record_telemetry(status_code, elapsed, metric_name, telemetry_runtime_produc
|
|
|
57
57
|
class FetchOptions(object):
|
|
58
58
|
"""Fetch Options object."""
|
|
59
59
|
|
|
60
|
-
def __init__(self, cache_control_headers=False, change_number=None, sets=None, spec=SPEC_VERSION):
|
|
60
|
+
def __init__(self, cache_control_headers=False, change_number=None, rbs_change_number=None, sets=None, spec=SPEC_VERSION):
|
|
61
61
|
"""
|
|
62
62
|
Class constructor.
|
|
63
63
|
|
|
@@ -72,6 +72,7 @@ class FetchOptions(object):
|
|
|
72
72
|
"""
|
|
73
73
|
self._cache_control_headers = cache_control_headers
|
|
74
74
|
self._change_number = change_number
|
|
75
|
+
self._rbs_change_number = rbs_change_number
|
|
75
76
|
self._sets = sets
|
|
76
77
|
self._spec = spec
|
|
77
78
|
|
|
@@ -85,6 +86,11 @@ class FetchOptions(object):
|
|
|
85
86
|
"""Return change number."""
|
|
86
87
|
return self._change_number
|
|
87
88
|
|
|
89
|
+
@property
|
|
90
|
+
def rbs_change_number(self):
|
|
91
|
+
"""Return change number."""
|
|
92
|
+
return self._rbs_change_number
|
|
93
|
+
|
|
88
94
|
@property
|
|
89
95
|
def sets(self):
|
|
90
96
|
"""Return sets."""
|
|
@@ -103,14 +109,19 @@ class FetchOptions(object):
|
|
|
103
109
|
if self._change_number != other._change_number:
|
|
104
110
|
return False
|
|
105
111
|
|
|
112
|
+
if self._rbs_change_number != other._rbs_change_number:
|
|
113
|
+
return False
|
|
114
|
+
|
|
106
115
|
if self._sets != other._sets:
|
|
107
116
|
return False
|
|
117
|
+
|
|
108
118
|
if self._spec != other._spec:
|
|
109
119
|
return False
|
|
120
|
+
|
|
110
121
|
return True
|
|
111
122
|
|
|
112
123
|
|
|
113
|
-
def build_fetch(change_number, fetch_options, metadata):
|
|
124
|
+
def build_fetch(change_number, fetch_options, metadata, rbs_change_number=None):
|
|
114
125
|
"""
|
|
115
126
|
Build fetch with new flags if that is the case.
|
|
116
127
|
|
|
@@ -123,11 +134,16 @@ def build_fetch(change_number, fetch_options, metadata):
|
|
|
123
134
|
:param metadata: Metadata Headers.
|
|
124
135
|
:type metadata: dict
|
|
125
136
|
|
|
137
|
+
:param rbs_change_number: Last known timestamp of a rule based segment modification.
|
|
138
|
+
:type rbs_change_number: int
|
|
139
|
+
|
|
126
140
|
:return: Objects for fetch
|
|
127
141
|
:rtype: dict, dict
|
|
128
142
|
"""
|
|
129
143
|
query = {'s': fetch_options.spec} if fetch_options.spec is not None else {}
|
|
130
144
|
query['since'] = change_number
|
|
145
|
+
if rbs_change_number is not None:
|
|
146
|
+
query['rbSince'] = rbs_change_number
|
|
131
147
|
extra_headers = metadata
|
|
132
148
|
if fetch_options is None:
|
|
133
149
|
return query, extra_headers
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"""Splits API module."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import json
|
|
5
|
+
|
|
6
|
+
from splitio.api import APIException, headers_from_metadata
|
|
7
|
+
from splitio.api.commons import build_fetch, FetchOptions
|
|
8
|
+
from splitio.api.client import HttpClientException
|
|
9
|
+
from splitio.models.telemetry import HTTPExceptionsAndLatencies
|
|
10
|
+
from splitio.util.time import utctime_ms
|
|
11
|
+
from splitio.spec import SPEC_VERSION
|
|
12
|
+
from splitio.sync import util
|
|
13
|
+
|
|
14
|
+
_LOGGER = logging.getLogger(__name__)
|
|
15
|
+
_SPEC_1_1 = "1.1"
|
|
16
|
+
_PROXY_CHECK_INTERVAL_MILLISECONDS_SS = 24 * 60 * 60 * 1000
|
|
17
|
+
|
|
18
|
+
class SplitsAPIBase(object): # pylint: disable=too-few-public-methods
|
|
19
|
+
"""Class that uses an httpClient to communicate with the splits API."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, client, sdk_key, sdk_metadata, telemetry_runtime_producer):
|
|
22
|
+
"""
|
|
23
|
+
Class constructor.
|
|
24
|
+
|
|
25
|
+
:param client: HTTP Client responsble for issuing calls to the backend.
|
|
26
|
+
:type client: HttpClient
|
|
27
|
+
:param sdk_key: User sdk_key token.
|
|
28
|
+
:type sdk_key: string
|
|
29
|
+
:param sdk_metadata: SDK version & machine name & IP.
|
|
30
|
+
:type sdk_metadata: splitio.client.util.SdkMetadata
|
|
31
|
+
"""
|
|
32
|
+
self._client = client
|
|
33
|
+
self._sdk_key = sdk_key
|
|
34
|
+
self._metadata = headers_from_metadata(sdk_metadata)
|
|
35
|
+
self._telemetry_runtime_producer = telemetry_runtime_producer
|
|
36
|
+
self._client.set_telemetry_data(HTTPExceptionsAndLatencies.SPLIT, self._telemetry_runtime_producer)
|
|
37
|
+
self._spec_version = SPEC_VERSION
|
|
38
|
+
self._last_proxy_check_timestamp = 0
|
|
39
|
+
self.clear_storage = False
|
|
40
|
+
self._old_spec_since = None
|
|
41
|
+
|
|
42
|
+
def _check_last_proxy_check_timestamp(self, since):
|
|
43
|
+
if self._spec_version == _SPEC_1_1 and ((utctime_ms() - self._last_proxy_check_timestamp) >= _PROXY_CHECK_INTERVAL_MILLISECONDS_SS):
|
|
44
|
+
_LOGGER.info("Switching to new Feature flag spec (%s) and fetching.", SPEC_VERSION);
|
|
45
|
+
self._spec_version = SPEC_VERSION
|
|
46
|
+
self._old_spec_since = since
|
|
47
|
+
|
|
48
|
+
def _check_old_spec_since(self, change_number):
|
|
49
|
+
if self._spec_version == _SPEC_1_1 and self._old_spec_since is not None:
|
|
50
|
+
since = self._old_spec_since
|
|
51
|
+
self._old_spec_since = None
|
|
52
|
+
return since
|
|
53
|
+
return change_number
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class SplitsAPI(SplitsAPIBase): # pylint: disable=too-few-public-methods
|
|
57
|
+
"""Class that uses an httpClient to communicate with the splits API."""
|
|
58
|
+
|
|
59
|
+
def __init__(self, client, sdk_key, sdk_metadata, telemetry_runtime_producer):
|
|
60
|
+
"""
|
|
61
|
+
Class constructor.
|
|
62
|
+
|
|
63
|
+
:param client: HTTP Client responsble for issuing calls to the backend.
|
|
64
|
+
:type client: HttpClient
|
|
65
|
+
:param sdk_key: User sdk_key token.
|
|
66
|
+
:type sdk_key: string
|
|
67
|
+
:param sdk_metadata: SDK version & machine name & IP.
|
|
68
|
+
:type sdk_metadata: splitio.client.util.SdkMetadata
|
|
69
|
+
"""
|
|
70
|
+
SplitsAPIBase.__init__(self, client, sdk_key, sdk_metadata, telemetry_runtime_producer)
|
|
71
|
+
|
|
72
|
+
def fetch_splits(self, change_number, rbs_change_number, fetch_options):
|
|
73
|
+
"""
|
|
74
|
+
Fetch feature flags from backend.
|
|
75
|
+
|
|
76
|
+
:param change_number: Last known timestamp of a split modification.
|
|
77
|
+
:type change_number: int
|
|
78
|
+
|
|
79
|
+
:param rbs_change_number: Last known timestamp of a rule based segment modification.
|
|
80
|
+
:type rbs_change_number: int
|
|
81
|
+
|
|
82
|
+
:param fetch_options: Fetch options for getting feature flag definitions.
|
|
83
|
+
:type fetch_options: splitio.api.commons.FetchOptions
|
|
84
|
+
|
|
85
|
+
:return: Json representation of a splitChanges response.
|
|
86
|
+
:rtype: dict
|
|
87
|
+
"""
|
|
88
|
+
try:
|
|
89
|
+
self._check_last_proxy_check_timestamp(change_number)
|
|
90
|
+
change_number = self._check_old_spec_since(change_number)
|
|
91
|
+
|
|
92
|
+
if self._spec_version == _SPEC_1_1:
|
|
93
|
+
fetch_options = FetchOptions(fetch_options.cache_control_headers, fetch_options.change_number,
|
|
94
|
+
None, fetch_options.sets, self._spec_version)
|
|
95
|
+
rbs_change_number = None
|
|
96
|
+
query, extra_headers = build_fetch(change_number, fetch_options, self._metadata, rbs_change_number)
|
|
97
|
+
response = self._client.get(
|
|
98
|
+
'sdk',
|
|
99
|
+
'splitChanges',
|
|
100
|
+
self._sdk_key,
|
|
101
|
+
extra_headers=extra_headers,
|
|
102
|
+
query=query,
|
|
103
|
+
)
|
|
104
|
+
if 200 <= response.status_code < 300:
|
|
105
|
+
if self._spec_version == _SPEC_1_1:
|
|
106
|
+
return util.convert_to_new_spec(json.loads(response.body))
|
|
107
|
+
|
|
108
|
+
self.clear_storage = self._last_proxy_check_timestamp != 0
|
|
109
|
+
self._last_proxy_check_timestamp = 0
|
|
110
|
+
return json.loads(response.body)
|
|
111
|
+
|
|
112
|
+
else:
|
|
113
|
+
if response.status_code == 414:
|
|
114
|
+
_LOGGER.error('Error fetching feature flags; the amount of flag sets provided are too big, causing uri length error.')
|
|
115
|
+
|
|
116
|
+
if self._client.is_sdk_endpoint_overridden() and response.status_code == 400 and self._spec_version == SPEC_VERSION:
|
|
117
|
+
_LOGGER.warning('Detected proxy response error, changing spec version from %s to %s and re-fetching.', self._spec_version, _SPEC_1_1)
|
|
118
|
+
self._spec_version = _SPEC_1_1
|
|
119
|
+
self._last_proxy_check_timestamp = utctime_ms()
|
|
120
|
+
return self.fetch_splits(change_number, None, FetchOptions(fetch_options.cache_control_headers, fetch_options.change_number,
|
|
121
|
+
None, fetch_options.sets, self._spec_version))
|
|
122
|
+
|
|
123
|
+
raise APIException(response.body, response.status_code)
|
|
124
|
+
|
|
125
|
+
except HttpClientException as exc:
|
|
126
|
+
_LOGGER.error('Error fetching feature flags because an exception was raised by the HTTPClient')
|
|
127
|
+
_LOGGER.debug('Error: ', exc_info=True)
|
|
128
|
+
raise APIException('Feature flags not fetched correctly.') from exc
|
|
129
|
+
|
|
130
|
+
class SplitsAPIAsync(SplitsAPIBase): # pylint: disable=too-few-public-methods
|
|
131
|
+
"""Class that uses an httpClient to communicate with the splits API."""
|
|
132
|
+
|
|
133
|
+
def __init__(self, client, sdk_key, sdk_metadata, telemetry_runtime_producer):
|
|
134
|
+
"""
|
|
135
|
+
Class constructor.
|
|
136
|
+
|
|
137
|
+
:param client: HTTP Client responsble for issuing calls to the backend.
|
|
138
|
+
:type client: HttpClient
|
|
139
|
+
:param sdk_key: User sdk_key token.
|
|
140
|
+
:type sdk_key: string
|
|
141
|
+
:param sdk_metadata: SDK version & machine name & IP.
|
|
142
|
+
:type sdk_metadata: splitio.client.util.SdkMetadata
|
|
143
|
+
"""
|
|
144
|
+
SplitsAPIBase.__init__(self, client, sdk_key, sdk_metadata, telemetry_runtime_producer)
|
|
145
|
+
|
|
146
|
+
async def fetch_splits(self, change_number, rbs_change_number, fetch_options):
|
|
147
|
+
"""
|
|
148
|
+
Fetch feature flags from backend.
|
|
149
|
+
|
|
150
|
+
:param change_number: Last known timestamp of a split modification.
|
|
151
|
+
:type change_number: int
|
|
152
|
+
|
|
153
|
+
:param rbs_change_number: Last known timestamp of a rule based segment modification.
|
|
154
|
+
:type rbs_change_number: int
|
|
155
|
+
|
|
156
|
+
:param fetch_options: Fetch options for getting feature flag definitions.
|
|
157
|
+
:type fetch_options: splitio.api.commons.FetchOptions
|
|
158
|
+
|
|
159
|
+
:return: Json representation of a splitChanges response.
|
|
160
|
+
:rtype: dict
|
|
161
|
+
"""
|
|
162
|
+
try:
|
|
163
|
+
self._check_last_proxy_check_timestamp(change_number)
|
|
164
|
+
change_number = self._check_old_spec_since(change_number)
|
|
165
|
+
if self._spec_version == _SPEC_1_1:
|
|
166
|
+
fetch_options = FetchOptions(fetch_options.cache_control_headers, fetch_options.change_number,
|
|
167
|
+
None, fetch_options.sets, self._spec_version)
|
|
168
|
+
rbs_change_number = None
|
|
169
|
+
|
|
170
|
+
query, extra_headers = build_fetch(change_number, fetch_options, self._metadata, rbs_change_number)
|
|
171
|
+
response = await self._client.get(
|
|
172
|
+
'sdk',
|
|
173
|
+
'splitChanges',
|
|
174
|
+
self._sdk_key,
|
|
175
|
+
extra_headers=extra_headers,
|
|
176
|
+
query=query,
|
|
177
|
+
)
|
|
178
|
+
if 200 <= response.status_code < 300:
|
|
179
|
+
if self._spec_version == _SPEC_1_1:
|
|
180
|
+
return util.convert_to_new_spec(json.loads(response.body))
|
|
181
|
+
|
|
182
|
+
self.clear_storage = self._last_proxy_check_timestamp != 0
|
|
183
|
+
self._last_proxy_check_timestamp = 0
|
|
184
|
+
return json.loads(response.body)
|
|
185
|
+
|
|
186
|
+
else:
|
|
187
|
+
if response.status_code == 414:
|
|
188
|
+
_LOGGER.error('Error fetching feature flags; the amount of flag sets provided are too big, causing uri length error.')
|
|
189
|
+
|
|
190
|
+
if self._client.is_sdk_endpoint_overridden() and response.status_code == 400 and self._spec_version == SPEC_VERSION:
|
|
191
|
+
_LOGGER.warning('Detected proxy response error, changing spec version from %s to %s and re-fetching.', self._spec_version, _SPEC_1_1)
|
|
192
|
+
self._spec_version = _SPEC_1_1
|
|
193
|
+
self._last_proxy_check_timestamp = utctime_ms()
|
|
194
|
+
return await self.fetch_splits(change_number, None, FetchOptions(fetch_options.cache_control_headers, fetch_options.change_number,
|
|
195
|
+
None, fetch_options.sets, self._spec_version))
|
|
196
|
+
|
|
197
|
+
raise APIException(response.body, response.status_code)
|
|
198
|
+
|
|
199
|
+
except HttpClientException as exc:
|
|
200
|
+
_LOGGER.error('Error fetching feature flags because an exception was raised by the HTTPClient')
|
|
201
|
+
_LOGGER.debug('Error: ', exc_info=True)
|
|
202
|
+
raise APIException('Feature flags not fetched correctly.') from exc
|
|
@@ -201,7 +201,7 @@ class Client(ClientBase): # pylint: disable=too-many-instance-attributes
|
|
|
201
201
|
:rtype: Client
|
|
202
202
|
"""
|
|
203
203
|
ClientBase.__init__(self, factory, recorder, labels_enabled)
|
|
204
|
-
self._context_factory = EvaluationDataFactory(factory._get_storage('splits'), factory._get_storage('segments'))
|
|
204
|
+
self._context_factory = EvaluationDataFactory(factory._get_storage('splits'), factory._get_storage('segments'), factory._get_storage('rule_based_segments'))
|
|
205
205
|
|
|
206
206
|
def destroy(self):
|
|
207
207
|
"""
|
|
@@ -668,7 +668,7 @@ class ClientAsync(ClientBase): # pylint: disable=too-many-instance-attributes
|
|
|
668
668
|
:rtype: Client
|
|
669
669
|
"""
|
|
670
670
|
ClientBase.__init__(self, factory, recorder, labels_enabled)
|
|
671
|
-
self._context_factory = AsyncEvaluationDataFactory(factory._get_storage('splits'), factory._get_storage('segments'))
|
|
671
|
+
self._context_factory = AsyncEvaluationDataFactory(factory._get_storage('splits'), factory._get_storage('segments'), factory._get_storage('rule_based_segments'))
|
|
672
672
|
|
|
673
673
|
async def destroy(self):
|
|
674
674
|
"""
|
|
@@ -23,14 +23,17 @@ from splitio.engine.impressions.unique_keys_tracker import UniqueKeysTracker, Un
|
|
|
23
23
|
from splitio.storage.inmemmory import InMemorySplitStorage, InMemorySegmentStorage, \
|
|
24
24
|
InMemoryImpressionStorage, InMemoryEventStorage, InMemoryTelemetryStorage, LocalhostTelemetryStorage, \
|
|
25
25
|
InMemorySplitStorageAsync, InMemorySegmentStorageAsync, InMemoryImpressionStorageAsync, \
|
|
26
|
-
InMemoryEventStorageAsync, InMemoryTelemetryStorageAsync, LocalhostTelemetryStorageAsync
|
|
26
|
+
InMemoryEventStorageAsync, InMemoryTelemetryStorageAsync, LocalhostTelemetryStorageAsync, \
|
|
27
|
+
InMemoryRuleBasedSegmentStorage, InMemoryRuleBasedSegmentStorageAsync
|
|
27
28
|
from splitio.storage.adapters import redis
|
|
28
29
|
from splitio.storage.redis import RedisSplitStorage, RedisSegmentStorage, RedisImpressionsStorage, \
|
|
29
30
|
RedisEventsStorage, RedisTelemetryStorage, RedisSplitStorageAsync, RedisEventsStorageAsync,\
|
|
30
|
-
RedisSegmentStorageAsync, RedisImpressionsStorageAsync, RedisTelemetryStorageAsync
|
|
31
|
+
RedisSegmentStorageAsync, RedisImpressionsStorageAsync, RedisTelemetryStorageAsync, \
|
|
32
|
+
RedisRuleBasedSegmentsStorage, RedisRuleBasedSegmentsStorageAsync
|
|
31
33
|
from splitio.storage.pluggable import PluggableEventsStorage, PluggableImpressionsStorage, PluggableSegmentStorage, \
|
|
32
34
|
PluggableSplitStorage, PluggableTelemetryStorage, PluggableTelemetryStorageAsync, PluggableEventsStorageAsync, \
|
|
33
|
-
PluggableImpressionsStorageAsync, PluggableSegmentStorageAsync, PluggableSplitStorageAsync
|
|
35
|
+
PluggableImpressionsStorageAsync, PluggableSegmentStorageAsync, PluggableSplitStorageAsync, \
|
|
36
|
+
PluggableRuleBasedSegmentsStorage, PluggableRuleBasedSegmentsStorageAsync
|
|
34
37
|
|
|
35
38
|
# APIs
|
|
36
39
|
from splitio.api.client import HttpClient, HttpClientAsync, HttpClientKerberos
|
|
@@ -543,6 +546,7 @@ def _build_in_memory_factory(api_key, cfg, sdk_url=None, events_url=None, # pyl
|
|
|
543
546
|
storages = {
|
|
544
547
|
'splits': InMemorySplitStorage(cfg['flagSetsFilter'] if cfg['flagSetsFilter'] is not None else []),
|
|
545
548
|
'segments': InMemorySegmentStorage(),
|
|
549
|
+
'rule_based_segments': InMemoryRuleBasedSegmentStorage(),
|
|
546
550
|
'impressions': InMemoryImpressionStorage(cfg['impressionsQueueSize'], telemetry_runtime_producer),
|
|
547
551
|
'events': InMemoryEventStorage(cfg['eventsQueueSize'], telemetry_runtime_producer),
|
|
548
552
|
}
|
|
@@ -559,8 +563,8 @@ def _build_in_memory_factory(api_key, cfg, sdk_url=None, events_url=None, # pyl
|
|
|
559
563
|
imp_strategy, none_strategy, telemetry_runtime_producer)
|
|
560
564
|
|
|
561
565
|
synchronizers = SplitSynchronizers(
|
|
562
|
-
SplitSynchronizer(apis['splits'], storages['splits']),
|
|
563
|
-
SegmentSynchronizer(apis['segments'], storages['splits'], storages['segments']),
|
|
566
|
+
SplitSynchronizer(apis['splits'], storages['splits'], storages['rule_based_segments']),
|
|
567
|
+
SegmentSynchronizer(apis['segments'], storages['splits'], storages['segments'], storages['rule_based_segments']),
|
|
564
568
|
ImpressionSynchronizer(apis['impressions'], storages['impressions'],
|
|
565
569
|
cfg['impressionsBulkSize']),
|
|
566
570
|
EventSynchronizer(apis['events'], storages['events'], cfg['eventsBulkSize']),
|
|
@@ -671,6 +675,7 @@ async def _build_in_memory_factory_async(api_key, cfg, sdk_url=None, events_url=
|
|
|
671
675
|
storages = {
|
|
672
676
|
'splits': InMemorySplitStorageAsync(cfg['flagSetsFilter'] if cfg['flagSetsFilter'] is not None else []),
|
|
673
677
|
'segments': InMemorySegmentStorageAsync(),
|
|
678
|
+
'rule_based_segments': InMemoryRuleBasedSegmentStorageAsync(),
|
|
674
679
|
'impressions': InMemoryImpressionStorageAsync(cfg['impressionsQueueSize'], telemetry_runtime_producer),
|
|
675
680
|
'events': InMemoryEventStorageAsync(cfg['eventsQueueSize'], telemetry_runtime_producer),
|
|
676
681
|
}
|
|
@@ -687,8 +692,8 @@ async def _build_in_memory_factory_async(api_key, cfg, sdk_url=None, events_url=
|
|
|
687
692
|
imp_strategy, none_strategy, telemetry_runtime_producer)
|
|
688
693
|
|
|
689
694
|
synchronizers = SplitSynchronizers(
|
|
690
|
-
SplitSynchronizerAsync(apis['splits'], storages['splits']),
|
|
691
|
-
SegmentSynchronizerAsync(apis['segments'], storages['splits'], storages['segments']),
|
|
695
|
+
SplitSynchronizerAsync(apis['splits'], storages['splits'], storages['rule_based_segments']),
|
|
696
|
+
SegmentSynchronizerAsync(apis['segments'], storages['splits'], storages['segments'], storages['rule_based_segments']),
|
|
692
697
|
ImpressionSynchronizerAsync(apis['impressions'], storages['impressions'],
|
|
693
698
|
cfg['impressionsBulkSize']),
|
|
694
699
|
EventSynchronizerAsync(apis['events'], storages['events'], cfg['eventsBulkSize']),
|
|
@@ -756,6 +761,7 @@ def _build_redis_factory(api_key, cfg):
|
|
|
756
761
|
storages = {
|
|
757
762
|
'splits': RedisSplitStorage(redis_adapter, cache_enabled, cache_ttl, []),
|
|
758
763
|
'segments': RedisSegmentStorage(redis_adapter),
|
|
764
|
+
'rule_based_segments': RedisRuleBasedSegmentsStorage(redis_adapter),
|
|
759
765
|
'impressions': RedisImpressionsStorage(redis_adapter, sdk_metadata),
|
|
760
766
|
'events': RedisEventsStorage(redis_adapter, sdk_metadata),
|
|
761
767
|
'telemetry': RedisTelemetryStorage(redis_adapter, sdk_metadata)
|
|
@@ -839,6 +845,7 @@ async def _build_redis_factory_async(api_key, cfg):
|
|
|
839
845
|
storages = {
|
|
840
846
|
'splits': RedisSplitStorageAsync(redis_adapter, cache_enabled, cache_ttl),
|
|
841
847
|
'segments': RedisSegmentStorageAsync(redis_adapter),
|
|
848
|
+
'rule_based_segments': RedisRuleBasedSegmentsStorageAsync(redis_adapter),
|
|
842
849
|
'impressions': RedisImpressionsStorageAsync(redis_adapter, sdk_metadata),
|
|
843
850
|
'events': RedisEventsStorageAsync(redis_adapter, sdk_metadata),
|
|
844
851
|
'telemetry': await RedisTelemetryStorageAsync.create(redis_adapter, sdk_metadata)
|
|
@@ -922,6 +929,7 @@ def _build_pluggable_factory(api_key, cfg):
|
|
|
922
929
|
storages = {
|
|
923
930
|
'splits': PluggableSplitStorage(pluggable_adapter, storage_prefix, []),
|
|
924
931
|
'segments': PluggableSegmentStorage(pluggable_adapter, storage_prefix),
|
|
932
|
+
'rule_based_segments': PluggableRuleBasedSegmentsStorage(pluggable_adapter, storage_prefix),
|
|
925
933
|
'impressions': PluggableImpressionsStorage(pluggable_adapter, sdk_metadata, storage_prefix),
|
|
926
934
|
'events': PluggableEventsStorage(pluggable_adapter, sdk_metadata, storage_prefix),
|
|
927
935
|
'telemetry': PluggableTelemetryStorage(pluggable_adapter, sdk_metadata, storage_prefix)
|
|
@@ -1003,6 +1011,7 @@ async def _build_pluggable_factory_async(api_key, cfg):
|
|
|
1003
1011
|
storages = {
|
|
1004
1012
|
'splits': PluggableSplitStorageAsync(pluggable_adapter, storage_prefix),
|
|
1005
1013
|
'segments': PluggableSegmentStorageAsync(pluggable_adapter, storage_prefix),
|
|
1014
|
+
'rule_based_segments': PluggableRuleBasedSegmentsStorageAsync(pluggable_adapter, storage_prefix),
|
|
1006
1015
|
'impressions': PluggableImpressionsStorageAsync(pluggable_adapter, sdk_metadata, storage_prefix),
|
|
1007
1016
|
'events': PluggableEventsStorageAsync(pluggable_adapter, sdk_metadata, storage_prefix),
|
|
1008
1017
|
'telemetry': await PluggableTelemetryStorageAsync.create(pluggable_adapter, sdk_metadata, storage_prefix)
|
|
@@ -1081,6 +1090,7 @@ def _build_localhost_factory(cfg):
|
|
|
1081
1090
|
storages = {
|
|
1082
1091
|
'splits': InMemorySplitStorage(cfg['flagSetsFilter'] if cfg['flagSetsFilter'] is not None else []),
|
|
1083
1092
|
'segments': InMemorySegmentStorage(), # not used, just to avoid possible future errors.
|
|
1093
|
+
'rule_based_segments': InMemoryRuleBasedSegmentStorage(),
|
|
1084
1094
|
'impressions': LocalhostImpressionsStorage(),
|
|
1085
1095
|
'events': LocalhostEventsStorage(),
|
|
1086
1096
|
}
|
|
@@ -1088,6 +1098,7 @@ def _build_localhost_factory(cfg):
|
|
|
1088
1098
|
synchronizers = SplitSynchronizers(
|
|
1089
1099
|
LocalSplitSynchronizer(cfg['splitFile'],
|
|
1090
1100
|
storages['splits'],
|
|
1101
|
+
storages['rule_based_segments'],
|
|
1091
1102
|
localhost_mode),
|
|
1092
1103
|
LocalSegmentSynchronizer(cfg['segmentDirectory'], storages['splits'], storages['segments']),
|
|
1093
1104
|
None, None, None,
|
|
@@ -1151,6 +1162,7 @@ async def _build_localhost_factory_async(cfg):
|
|
|
1151
1162
|
storages = {
|
|
1152
1163
|
'splits': InMemorySplitStorageAsync(),
|
|
1153
1164
|
'segments': InMemorySegmentStorageAsync(), # not used, just to avoid possible future errors.
|
|
1165
|
+
'rule_based_segments': InMemoryRuleBasedSegmentStorageAsync(),
|
|
1154
1166
|
'impressions': LocalhostImpressionsStorageAsync(),
|
|
1155
1167
|
'events': LocalhostEventsStorageAsync(),
|
|
1156
1168
|
}
|
|
@@ -1158,6 +1170,7 @@ async def _build_localhost_factory_async(cfg):
|
|
|
1158
1170
|
synchronizers = SplitSynchronizers(
|
|
1159
1171
|
LocalSplitSynchronizerAsync(cfg['splitFile'],
|
|
1160
1172
|
storages['splits'],
|
|
1173
|
+
storages['rule_based_segments'],
|
|
1161
1174
|
localhost_mode),
|
|
1162
1175
|
LocalSegmentSynchronizerAsync(cfg['segmentDirectory'], storages['splits'], storages['segments']),
|
|
1163
1176
|
None, None, None,
|