Skip to content

Commit f673a32

Browse files
add stop method to polling config manager (#410)
1 parent 9f46ddf commit f673a32

File tree

4 files changed

+59
-144
lines changed

4 files changed

+59
-144
lines changed

optimizely/config_manager.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from typing import TYPE_CHECKING, Any, Optional
1818
import requests
1919
import threading
20-
import time
2120
from requests import codes as http_status_codes
2221
from requests import exceptions as requests_exceptions
2322

@@ -216,8 +215,8 @@ def __init__(
216215
self.set_update_interval(update_interval)
217216
self.set_blocking_timeout(blocking_timeout)
218217
self.last_modified: Optional[str] = None
219-
self._polling_thread = threading.Thread(target=self._run)
220-
self._polling_thread.daemon = True
218+
self.stopped = threading.Event()
219+
self._initialize_thread()
221220
self._polling_thread.start()
222221

223222
@staticmethod
@@ -375,15 +374,23 @@ def is_running(self) -> bool:
375374
""" Check if polling thread is alive or not. """
376375
return self._polling_thread.is_alive()
377376

377+
def stop(self) -> None:
378+
""" Stop the polling thread and wait for it to exit. """
379+
if self.is_running:
380+
self.stopped.set()
381+
self._polling_thread.join()
382+
378383
def _run(self) -> None:
379384
""" Triggered as part of the thread which fetches the datafile and sleeps until next update interval. """
380385
try:
381-
while self.is_running:
386+
while True:
382387
self.fetch_datafile()
383-
time.sleep(self.update_interval)
388+
if self.stopped.wait(self.update_interval):
389+
self.stopped.clear()
390+
break
384391
except (OSError, OverflowError) as err:
385392
self.logger.error(
386-
f'Error in time.sleep. Provided update_interval value may be too big. Error: {err}'
393+
f'Provided update_interval value may be too big. Error: {err}'
387394
)
388395
raise
389396

@@ -392,6 +399,9 @@ def start(self) -> None:
392399
if not self.is_running:
393400
self._polling_thread.start()
394401

402+
def _initialize_thread(self) -> None:
403+
self._polling_thread = threading.Thread(target=self._run, daemon=True)
404+
395405

396406
class AuthDatafilePollingConfigManager(PollingConfigManager):
397407
""" Config manager that polls for authenticated datafile using access token. """

optimizely/optimizely.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,9 @@ def __init__(
8888
config_manager.BaseConfigManager implementation which can be using the
8989
same NotificationCenter instance.
9090
event_processor: Optional component which processes the given event(s).
91-
By default optimizely.event.event_processor.ForwardingEventProcessor is used
92-
which simply forwards events to the event dispatcher.
93-
To enable event batching configure and use
94-
optimizely.event.event_processor.BatchEventProcessor.
91+
By default optimizely.event.event_processor.BatchEventProcessor is used
92+
which batches events. To simply forward events to the event dispatcher
93+
configure and use optimizely.event.event_processor.ForwardingEventProcessor.
9594
datafile_access_token: Optional string used to fetch authenticated datafile for a secure project environment.
9695
default_decide_options: Optional list of decide options used with the decide APIs.
9796
event_processor_options: Optional dict of options to be passed to the default batch event processor.
@@ -1381,3 +1380,5 @@ def close(self) -> None:
13811380
if callable(getattr(self.event_processor, 'stop', None)):
13821381
self.event_processor.stop() # type: ignore[attr-defined]
13831382
self.odp_manager.close()
1383+
if callable(getattr(self.config_manager, 'stop', None)):
1384+
self.config_manager.stop() # type: ignore[attr-defined]

requirements/typing.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
mypy
1+
mypy==0.982
22
types-jsonschema
33
types-requests
44
types-Flask

0 commit comments

Comments
 (0)