Skip to content

Commit 9ffd339

Browse files
committed
polishing
1 parent a11c897 commit 9ffd339

File tree

4 files changed

+57
-31
lines changed

4 files changed

+57
-31
lines changed

splitio/api/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ def status_code(self):
1414
"""Return HTTP status code."""
1515
return self._status_code
1616

17+
class APIUriException(APIException):
18+
"""Exception to raise when an API call fails due to 414 http error."""
19+
20+
def __init__(self, custom_message, status_code=None):
21+
"""Constructor."""
22+
APIException.__init__(self, custom_message)
23+
1724
def headers_from_metadata(sdk_metadata, client_key=None):
1825
"""
1926
Generate a dict with headers required by data-recording API endpoints.

splitio/sync/manager.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ def __init__(self, synchronizer): # pylint:disable=too-many-arguments
285285
:param synchronizer: synchronizers for performing start/stop logic
286286
:type synchronizer: splitio.sync.synchronizer.Synchronizer
287287
"""
288-
super().__init__(synchronizer)
288+
RedisManagerBase.__init__(self, synchronizer)
289289

290290
def stop(self, blocking):
291291
"""
@@ -308,7 +308,7 @@ def __init__(self, synchronizer): # pylint:disable=too-many-arguments
308308
:param synchronizer: synchronizers for performing start/stop logic
309309
:type synchronizer: splitio.sync.synchronizer.Synchronizer
310310
"""
311-
super().__init__(synchronizer)
311+
RedisManagerBase.__init__(self, synchronizer)
312312

313313
async def stop(self, blocking):
314314
"""

splitio/sync/split.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import hashlib
99
from enum import Enum
1010

11-
from splitio.api import APIException
11+
from splitio.api import APIException, APIUriException
1212
from splitio.api.commons import FetchOptions
1313
from splitio.client.input_validator import validate_flag_sets
1414
from splitio.models import splits
@@ -77,7 +77,7 @@ def __init__(self, feature_flag_api, feature_flag_storage):
7777
:param feature_flag_storage: Feature Flag Storage.
7878
:type feature_flag_storage: splitio.storage.InMemorySplitStorage
7979
"""
80-
super().__init__(feature_flag_api, feature_flag_storage)
80+
SplitSynchronizerBase.__init__(self, feature_flag_api, feature_flag_storage)
8181

8282
def _fetch_until(self, fetch_options, till=None):
8383
"""
@@ -104,12 +104,16 @@ def _fetch_until(self, fetch_options, till=None):
104104
try:
105105
feature_flag_changes = self._api.fetch_splits(change_number, fetch_options)
106106
except APIException as exc:
107+
if exc._status_code is not None and exc._status_code == 414:
108+
_LOGGER.error('SDK Initialization: the amount of flag sets provided are big causing uri length error.')
109+
_LOGGER.debug('Exception information: ', exc_info=True)
110+
raise APIUriException("URI is too long due to FlagSets count")
111+
107112
_LOGGER.error('Exception raised while fetching feature flags')
108113
_LOGGER.debug('Exception information: ', exc_info=True)
109114
raise exc
110115

111-
fetched_feature_flags = []
112-
[fetched_feature_flags.append(splits.from_raw(feature_flag)) for feature_flag in feature_flag_changes.get('splits', [])]
116+
fetched_feature_flags = [(splits.from_raw(feature_flag)) for feature_flag in feature_flag_changes.get('splits', [])]
113117
segment_list = update_feature_flag_storage(self._feature_flag_storage, fetched_feature_flags, feature_flag_changes['till'])
114118
if feature_flag_changes['till'] == feature_flag_changes['since']:
115119
return feature_flag_changes['till'], segment_list
@@ -195,7 +199,7 @@ def __init__(self, feature_flag_api, feature_flag_storage):
195199
:param feature_flag_storage: Feature Flag Storage.
196200
:type feature_flag_storage: splitio.storage.InMemorySplitStorage
197201
"""
198-
super().__init__(feature_flag_api, feature_flag_storage)
202+
SplitSynchronizerBase.__init__(self, feature_flag_api, feature_flag_storage)
199203

200204
async def _fetch_until(self, fetch_options, till=None):
201205
"""
@@ -222,12 +226,16 @@ async def _fetch_until(self, fetch_options, till=None):
222226
try:
223227
feature_flag_changes = await self._api.fetch_splits(change_number, fetch_options)
224228
except APIException as exc:
229+
if exc._status_code is not None and exc._status_code == 414:
230+
_LOGGER.error('Exception caught: the amount of flag sets provided are big causing uri length error.')
231+
_LOGGER.debug('Exception information: ', exc_info=True)
232+
raise APIUriException("URI is too long due to FlagSets count")
233+
225234
_LOGGER.error('Exception raised while fetching feature flags')
226235
_LOGGER.debug('Exception information: ', exc_info=True)
227236
raise exc
228237

229-
fetched_feature_flags = []
230-
[fetched_feature_flags.append(splits.from_raw(feature_flag)) for feature_flag in feature_flag_changes.get('splits', [])]
238+
fetched_feature_flags = [(splits.from_raw(feature_flag)) for feature_flag in feature_flag_changes.get('splits', [])]
231239
segment_list = await update_feature_flag_storage_async(self._feature_flag_storage, fetched_feature_flags, feature_flag_changes['till'])
232240
if feature_flag_changes['till'] == feature_flag_changes['since']:
233241
return feature_flag_changes['till'], segment_list
@@ -597,7 +605,7 @@ def synchronize_splits(self, till=None): # pylint:disable=unused-argument
597605
try:
598606
return self._synchronize_json() if self._localhost_mode == LocalhostMode.JSON else self._synchronize_legacy()
599607
except Exception as exc:
600-
_LOGGER.error(str(exc))
608+
_LOGGER.debug('Exception: ', exc_info=True)
601609
raise APIException("Error fetching feature flags information") from exc
602610

603611
def _synchronize_legacy(self):
@@ -639,7 +647,7 @@ def _synchronize_json(self):
639647
segment_list = update_feature_flag_storage(self._feature_flag_storage, fetched_feature_flags, till)
640648
return segment_list
641649
except Exception as exc:
642-
_LOGGER.debug(exc)
650+
_LOGGER.debug('Exception: ', exc_info=True)
643651
raise ValueError("Error reading feature flags from json.") from exc
644652

645653
def _read_feature_flags_from_json_file(self, filename):
@@ -658,7 +666,7 @@ def _read_feature_flags_from_json_file(self, filename):
658666
santitized = self._sanitize_feature_flag(parsed)
659667
return santitized['splits'], santitized['till']
660668
except Exception as exc:
661-
_LOGGER.error(str(exc))
669+
_LOGGER.debug('Exception: ', exc_info=True)
662670
raise ValueError("Error parsing file %s. Make sure it's readable." % filename) from exc
663671

664672

@@ -741,7 +749,7 @@ async def synchronize_splits(self, till=None): # pylint:disable=unused-argument
741749
try:
742750
return await self._synchronize_json() if self._localhost_mode == LocalhostMode.JSON else await self._synchronize_legacy()
743751
except Exception as exc:
744-
_LOGGER.error(str(exc))
752+
_LOGGER.debug('Exception: ', exc_info=True)
745753
raise APIException("Error fetching feature flags information") from exc
746754

747755
async def _synchronize_legacy(self):
@@ -783,7 +791,7 @@ async def _synchronize_json(self):
783791
segment_list = await update_feature_flag_storage_async(self._feature_flag_storage, fetched_feature_flags, till)
784792
return segment_list
785793
except Exception as exc:
786-
_LOGGER.debug(exc)
794+
_LOGGER.debug('Exception: ', exc_info=True)
787795
raise ValueError("Error reading feature flags from json.") from exc
788796

789797
async def _read_feature_flags_from_json_file(self, filename):
@@ -802,5 +810,5 @@ async def _read_feature_flags_from_json_file(self, filename):
802810
santitized = self._sanitize_feature_flag(parsed)
803811
return santitized['splits'], santitized['till']
804812
except Exception as exc:
805-
_LOGGER.error(str(exc))
813+
_LOGGER.debug('Exception: ', exc_info=True)
806814
raise ValueError("Error parsing file %s. Make sure it's readable." % filename) from exc

splitio/sync/synchronizer.py

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import time
77

88
from splitio.optional.loaders import asyncio
9-
from splitio.api import APIException
9+
from splitio.api import APIException, APIUriException
1010
from splitio.util.backoff import Backoff
1111
from splitio.sync.split import _ON_DEMAND_FETCH_BACKOFF_BASE, _ON_DEMAND_FETCH_BACKOFF_MAX_RETRIES, _ON_DEMAND_FETCH_BACKOFF_MAX_WAIT, LocalhostMode
1212

@@ -252,7 +252,6 @@ def __init__(self, split_synchronizers, split_tasks):
252252
self._periodic_data_recording_tasks.append(self._split_tasks.unique_keys_task)
253253
if self._split_tasks.clear_filter_task:
254254
self._periodic_data_recording_tasks.append(self._split_tasks.clear_filter_task)
255-
self._break_sync_all = False
256255

257256
@property
258257
def split_sync(self):
@@ -354,7 +353,7 @@ def __init__(self, split_synchronizers, split_tasks):
354353
:param split_tasks: tasks for starting/stopping tasks
355354
:type split_tasks: splitio.sync.synchronizer.SplitTasks
356355
"""
357-
super().__init__(split_synchronizers, split_tasks)
356+
SynchronizerInMemoryBase.__init__(self, split_synchronizers, split_tasks)
358357

359358
def _synchronize_segments(self):
360359
_LOGGER.debug('Starting segments synchronization')
@@ -385,7 +384,6 @@ def synchronize_splits(self, till, sync_segments=True):
385384
:returns: whether the synchronization was successful or not.
386385
:rtype: bool
387386
"""
388-
self._break_sync_all = False
389387
_LOGGER.debug('Starting splits synchronization')
390388
try:
391389
new_segments = []
@@ -401,9 +399,12 @@ def synchronize_splits(self, till, sync_segments=True):
401399
else:
402400
_LOGGER.debug('Segment sync scheduled.')
403401
return True
402+
except APIUriException as exc:
403+
_LOGGER.error('Failed syncing feature flags due to long URI')
404+
_LOGGER.debug('Error: ', exc_info=True)
405+
return False
406+
404407
except APIException as exc:
405-
if exc._status_code is not None and exc._status_code == 414:
406-
self._break_sync_all = True
407408
_LOGGER.error('Failed syncing feature flags')
408409
_LOGGER.debug('Error: ', exc_info=True)
409410
return False
@@ -428,12 +429,16 @@ def sync_all(self, max_retry_attempts=_SYNC_ALL_NO_RETRIES):
428429

429430
# All is good
430431
return
432+
except APIUriException as exc:
433+
_LOGGER.error("URI too long exception, aborting retries.")
434+
_LOGGER.debug('Error: ', exc_info=True)
435+
break
431436
except Exception as exc: # pylint:disable=broad-except
432437
_LOGGER.error("Exception caught when trying to sync all data: %s", str(exc))
433438
_LOGGER.debug('Error: ', exc_info=True)
434439
if max_retry_attempts != _SYNC_ALL_NO_RETRIES:
435440
retry_attempts += 1
436-
if retry_attempts > max_retry_attempts or self._break_sync_all:
441+
if retry_attempts > max_retry_attempts:
437442
break
438443
how_long = self._backoff.get()
439444
time.sleep(how_long)
@@ -508,7 +513,7 @@ def __init__(self, split_synchronizers, split_tasks):
508513
:param split_tasks: tasks for starting/stopping tasks
509514
:type split_tasks: splitio.sync.synchronizer.SplitTasks
510515
"""
511-
super().__init__(split_synchronizers, split_tasks)
516+
SynchronizerInMemoryBase.__init__(self, split_synchronizers, split_tasks)
512517
self.stop_periodic_data_recording_task = None
513518

514519
async def _synchronize_segments(self):
@@ -540,7 +545,6 @@ async def synchronize_splits(self, till, sync_segments=True):
540545
:returns: whether the synchronization was successful or not.
541546
:rtype: bool
542547
"""
543-
self._break_sync_all = False
544548
_LOGGER.debug('Starting feature flags synchronization')
545549
try:
546550
new_segments = []
@@ -556,9 +560,12 @@ async def synchronize_splits(self, till, sync_segments=True):
556560
else:
557561
_LOGGER.debug('Segment sync scheduled.')
558562
return True
563+
except APIUriException as exc:
564+
_LOGGER.error('Failed syncing feature flags due to long URI')
565+
_LOGGER.debug('Error: ', exc_info=True)
566+
return False
567+
559568
except APIException as exc:
560-
if exc._status_code is not None and exc._status_code == 414:
561-
self._break_sync_all = True
562569
_LOGGER.error('Failed syncing feature flags')
563570
_LOGGER.debug('Error: ', exc_info=True)
564571
return False
@@ -583,12 +590,16 @@ async def sync_all(self, max_retry_attempts=_SYNC_ALL_NO_RETRIES):
583590

584591
# All is good
585592
return
593+
except APIUriException as exc:
594+
_LOGGER.error("URI too long exception, aborting retries.")
595+
_LOGGER.debug('Error: ', exc_info=True)
596+
break
586597
except Exception as exc: # pylint:disable=broad-except
587598
_LOGGER.error("Exception caught when trying to sync all data: %s", str(exc))
588599
_LOGGER.debug('Error: ', exc_info=True)
589600
if max_retry_attempts != _SYNC_ALL_NO_RETRIES:
590601
retry_attempts += 1
591-
if retry_attempts > max_retry_attempts or self._break_sync_all:
602+
if retry_attempts > max_retry_attempts:
592603
break
593604
how_long = self._backoff.get()
594605
time.sleep(how_long)
@@ -734,7 +745,7 @@ def __init__(self, split_synchronizers, split_tasks):
734745
:param split_tasks: tasks for starting/stopping tasks
735746
:type split_tasks: splitio.sync.synchronizer.SplitTasks
736747
"""
737-
super().__init__(split_synchronizers, split_tasks)
748+
RedisSynchronizerBase.__init__(self, split_synchronizers, split_tasks)
738749

739750
def shutdown(self, blocking):
740751
"""
@@ -779,7 +790,7 @@ def __init__(self, split_synchronizers, split_tasks):
779790
:param split_tasks: tasks for starting/stopping tasks
780791
:type split_tasks: splitio.sync.synchronizer.SplitTasks
781792
"""
782-
super().__init__(split_synchronizers, split_tasks)
793+
RedisSynchronizerBase.__init__(self, split_synchronizers, split_tasks)
783794
self.stop_periodic_data_recording_task = None
784795

785796
async def shutdown(self, blocking):
@@ -895,7 +906,7 @@ def __init__(self, split_synchronizers, split_tasks, localhost_mode):
895906
:param split_tasks: tasks for starting/stopping tasks
896907
:type split_tasks: splitio.sync.synchronizer.SplitTasks
897908
"""
898-
super().__init__(split_synchronizers, split_tasks, localhost_mode)
909+
LocalhostSynchronizerBase.__init__(self, split_synchronizers, split_tasks, localhost_mode)
899910

900911
def sync_all(self, till=None):
901912
"""
@@ -969,7 +980,7 @@ def __init__(self, split_synchronizers, split_tasks, localhost_mode):
969980
:param split_tasks: tasks for starting/stopping tasks
970981
:type split_tasks: splitio.sync.synchronizer.SplitTasks
971982
"""
972-
super().__init__(split_synchronizers, split_tasks, localhost_mode)
983+
LocalhostSynchronizerBase.__init__(self, split_synchronizers, split_tasks, localhost_mode)
973984

974985
async def sync_all(self, till=None):
975986
"""

0 commit comments

Comments
 (0)