Skip to content

Commit 9aa12a8

Browse files
authored
Merge pull request splitio#237 from splitio/development
Development
2 parents bd7e52b + 15537fb commit 9aa12a8

24 files changed

+531
-107
lines changed

CHANGES.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
9.1.0 (Jul 15, 2021)
2+
- Added Cache-Control header for on-demand requests to sdk-server.
3+
- Updated the synchronization flow to be more reliable in the event of an edge case generating delay in cache purge propagation, keeping the SDK cache properly synced.
4+
15
9.0.0 (May 3, 2021)
26
- BREAKING CHANGE: Removed splitSdkMachineIp and splitSdkMachineName configs.
37
- BREAKING CHANGE: Deprecated `redisCharset` config.

splitio/api/__init__.py

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,3 @@ def __init__(self, custom_message, status_code=None):
1313
def status_code(self):
1414
"""Return HTTP status code."""
1515
return self._status_code
16-
17-
18-
def headers_from_metadata(sdk_metadata, client_key=None):
19-
"""
20-
Generate a dict with headers required by data-recording API endpoints.
21-
22-
:param sdk_metadata: SDK Metadata object, generated at sdk initialization time.
23-
:type sdk_metadata: splitio.client.util.SdkMetadata
24-
25-
:param client_key: client key.
26-
:type client_key: str
27-
28-
:return: A dictionary with headers.
29-
:rtype: dict
30-
"""
31-
32-
metadata = {
33-
'SplitSDKVersion': sdk_metadata.sdk_version,
34-
'SplitSDKMachineIP': sdk_metadata.instance_ip,
35-
'SplitSDKMachineName': sdk_metadata.instance_name
36-
} if sdk_metadata.instance_ip != 'NA' and sdk_metadata.instance_ip != 'unknown' else {
37-
'SplitSDKVersion': sdk_metadata.sdk_version,
38-
}
39-
40-
if client_key is not None:
41-
metadata['SplitSDKClientKey'] = client_key
42-
43-
return metadata

splitio/api/auth.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import logging
44
import json
55

6-
from splitio.api import APIException, headers_from_metadata
6+
from splitio.api import APIException
7+
from splitio.api.commons import headers_from_metadata
78
from splitio.api.client import HttpClientException
89
from splitio.models.token import from_raw
910

splitio/api/commons.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
"""Commons module."""
2+
3+
4+
_CACHE_CONTROL = 'Cache-Control'
5+
_CACHE_CONTROL_NO_CACHE = 'no-cache'
6+
7+
8+
def headers_from_metadata(sdk_metadata, client_key=None):
9+
"""
10+
Generate a dict with headers required by data-recording API endpoints.
11+
12+
:param sdk_metadata: SDK Metadata object, generated at sdk initialization time.
13+
:type sdk_metadata: splitio.client.util.SdkMetadata
14+
15+
:param client_key: client key.
16+
:type client_key: str
17+
18+
:return: A dictionary with headers.
19+
:rtype: dict
20+
"""
21+
22+
metadata = {
23+
'SplitSDKVersion': sdk_metadata.sdk_version,
24+
'SplitSDKMachineIP': sdk_metadata.instance_ip,
25+
'SplitSDKMachineName': sdk_metadata.instance_name
26+
} if sdk_metadata.instance_ip != 'NA' and sdk_metadata.instance_ip != 'unknown' else {
27+
'SplitSDKVersion': sdk_metadata.sdk_version,
28+
}
29+
30+
if client_key is not None:
31+
metadata['SplitSDKClientKey'] = client_key
32+
33+
return metadata
34+
35+
36+
class FetchOptions(object):
37+
"""Fetch Options object."""
38+
39+
def __init__(self, cache_control_headers=False, change_number=None):
40+
"""
41+
Class constructor.
42+
43+
:param cache_control_headers: Flag for Cache-Control header
44+
:type cache_control_headers: bool
45+
46+
:param change_number: ChangeNumber to use for bypassing CDN in request.
47+
:type change_number: int
48+
"""
49+
self._cache_control_headers = cache_control_headers
50+
self._change_number = change_number
51+
52+
@property
53+
def cache_control_headers(self):
54+
"""Return cache control headers."""
55+
return self._cache_control_headers
56+
57+
@property
58+
def change_number(self):
59+
"""Return change number."""
60+
return self._change_number
61+
62+
def __eq__(self, other):
63+
"""Match between other options."""
64+
if self._cache_control_headers != other._cache_control_headers:
65+
return False
66+
if self._change_number != other._change_number:
67+
return False
68+
return True
69+
70+
71+
def build_fetch(change_number, fetch_options, metadata):
72+
"""
73+
Build fetch with new flags if that is the case.
74+
75+
:param change_number: Last known timestamp of definition.
76+
:type change_number: int
77+
78+
:param fetch_options: Fetch options for getting definitions.
79+
:type fetch_options: splitio.api.commons.FetchOptions
80+
81+
:param metadata: Metadata Headers.
82+
:type metadata: dict
83+
84+
:return: Objects for fetch
85+
:rtype: dict, dict
86+
"""
87+
query = {'since': change_number}
88+
extra_headers = metadata
89+
if fetch_options is None:
90+
return query, extra_headers
91+
if fetch_options.cache_control_headers:
92+
extra_headers[_CACHE_CONTROL] = _CACHE_CONTROL_NO_CACHE
93+
if fetch_options.change_number is not None:
94+
query['till'] = fetch_options.change_number
95+
return query, extra_headers

splitio/api/events.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
"""Events API module."""
22
import logging
33

4-
from splitio.api import APIException, headers_from_metadata
4+
from splitio.api import APIException
55
from splitio.api.client import HttpClientException
6+
from splitio.api.commons import headers_from_metadata
67

78

89
_LOGGER = logging.getLogger(__name__)

splitio/api/impressions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
import logging
44
from itertools import groupby
55

6-
from splitio.api import APIException, headers_from_metadata
6+
from splitio.api import APIException
77
from splitio.api.client import HttpClientException
8+
from splitio.api.commons import headers_from_metadata
89
from splitio.engine.impressions import ImpressionsMode
910

1011

splitio/api/segments.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import json
44
import logging
55

6-
from splitio.api import APIException, headers_from_metadata
6+
from splitio.api import APIException
7+
from splitio.api.commons import headers_from_metadata, build_fetch
78
from splitio.api.client import HttpClientException
89

910

@@ -29,25 +30,30 @@ def __init__(self, http_client, apikey, sdk_metadata):
2930
self._apikey = apikey
3031
self._metadata = headers_from_metadata(sdk_metadata)
3132

32-
def fetch_segment(self, segment_name, change_number):
33+
def fetch_segment(self, segment_name, change_number, fetch_options):
3334
"""
3435
Fetch splits from backend.
3536
3637
:param segment_name: Name of the segment to fetch changes for.
3738
:type segment_name: str
38-
:param change_number: Last known timestamp of a split modification.
39+
40+
:param change_number: Last known timestamp of a segment modification.
3941
:type change_number: int
4042
43+
:param fetch_options: Fetch options for getting segment definitions.
44+
:type fetch_options: splitio.api.commons.FetchOptions
45+
4146
:return: Json representation of a segmentChange response.
4247
:rtype: dict
4348
"""
4449
try:
50+
query, extra_headers = build_fetch(change_number, fetch_options, self._metadata)
4551
response = self._client.get(
4652
'sdk',
4753
'/segmentChanges/{segment_name}'.format(segment_name=segment_name),
4854
self._apikey,
49-
extra_headers=self._metadata,
50-
query={'since': change_number}
55+
extra_headers=extra_headers,
56+
query=query,
5157
)
5258

5359
if 200 <= response.status_code < 300:

splitio/api/splits.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import logging
44
import json
55

6-
from splitio.api import APIException, headers_from_metadata
6+
from splitio.api import APIException
7+
from splitio.api.commons import headers_from_metadata, build_fetch
78
from splitio.api.client import HttpClientException
89

910

@@ -28,23 +29,27 @@ def __init__(self, client, apikey, sdk_metadata):
2829
self._apikey = apikey
2930
self._metadata = headers_from_metadata(sdk_metadata)
3031

31-
def fetch_splits(self, change_number):
32+
def fetch_splits(self, change_number, fetch_options):
3233
"""
3334
Fetch splits from backend.
3435
35-
:param changeNumber: Last known timestamp of a split modification.
36-
:type changeNumber: int
36+
:param change_number: Last known timestamp of a split modification.
37+
:type change_number: int
38+
39+
:param fetch_options: Fetch options for getting split definitions.
40+
:type fetch_options: splitio.api.commons.FetchOptions
3741
3842
:return: Json representation of a splitChanges response.
3943
:rtype: dict
4044
"""
4145
try:
46+
query, extra_headers = build_fetch(change_number, fetch_options, self._metadata)
4247
response = self._client.get(
4348
'sdk',
4449
'/splitChanges',
4550
self._apikey,
46-
extra_headers=self._metadata,
47-
query={'since': change_number}
51+
extra_headers=extra_headers,
52+
query=query,
4853
)
4954
if 200 <= response.status_code < 300:
5055
return json.loads(response.body)

splitio/api/telemetry.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"""Telemetry API Module."""
22
import logging
33

4-
from splitio.api import APIException, headers_from_metadata
4+
from splitio.api import APIException
5+
from splitio.api.commons import headers_from_metadata
56
from splitio.api.client import HttpClientException
67

78

splitio/client/input_validator.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import math
66

77
from splitio.api import APIException
8+
from splitio.api.commons import FetchOptions
89
from splitio.client.key import Key
910
from splitio.engine.evaluator import CONTROL
1011

@@ -458,7 +459,7 @@ def validate_apikey_type(segment_api):
458459
_logger = logging.getLogger('splitio.api.segments')
459460
try:
460461
_logger.addFilter(api_messages_filter) # pylint: disable=protected-access
461-
segment_api.fetch_segment('__SOME_INVALID_SEGMENT__', -1)
462+
segment_api.fetch_segment('__SOME_INVALID_SEGMENT__', -1, FetchOptions())
462463
except APIException as exc:
463464
if exc.status_code == 403:
464465
_LOGGER.error('factory instantiation: you passed a browser type '

0 commit comments

Comments
 (0)