11import collections
2+ import concurrent .futures
23import threading
3- from typing import Optional , Union
44
5+ from typing import Optional , Union
56from .retryable_logs import RetryableLogs
67from .evaluation_details import EvaluationDetails
78from .evaluator import _ConfigEvaluation
89from .statsig_event import StatsigEvent
9- # from .statsig_user import StatsigUser
1010from .layer import Layer
1111from .utils import logger
1212from .thread_util import spawn_background_thread , THREAD_JOIN_TIMEOUT
1919
2020_IGNORED_METADATA_KEYS = {'serverTime' , 'configSyncTime' , 'initTime' , 'reason' }
2121
22+
2223def _safe_add_evaluation_to_event (
2324 evaluation_details : Union [EvaluationDetails , None ], event : StatsigEvent ):
2425 if evaluation_details is None or event is None or event .metadata is None :
@@ -52,6 +53,8 @@ def __init__(self, net, shutdown_event, statsig_metadata, error_boundary, option
5253 self ._background_retry = None
5354 self ._background_deduper = None
5455 self .spawn_bg_threads_if_needed ()
56+ self ._executor = concurrent .futures .ThreadPoolExecutor (max_workers = 4 )
57+ self ._futures = []
5558
5659 def spawn_bg_threads_if_needed (self ):
5760 if self ._local_mode :
@@ -74,7 +77,7 @@ def log(self, event):
7477 return
7578 self ._events .append (event .to_dict ())
7679 if len (self ._events ) >= self ._event_queue_size :
77- self .flush ()
80+ self ._run_on_background_thread ( lambda : self . flush () )
7881
7982 def log_gate_exposure (self , user , gate , value , rule_id , secondary_exposures ,
8083 evaluation_details : EvaluationDetails , is_manual_exposure = False ):
@@ -168,6 +171,16 @@ def shutdown(self):
168171 if self ._background_retry is not None :
169172 self ._background_retry .join (THREAD_JOIN_TIMEOUT )
170173
174+ concurrent .futures .wait (self ._futures , timeout = THREAD_JOIN_TIMEOUT )
175+ self ._executor .shutdown ()
176+
177+ def _run_on_background_thread (self , closure ):
178+ future = self ._executor .submit (closure )
179+ self ._futures .append (future )
180+
181+ for future in concurrent .futures .as_completed (self ._futures ):
182+ self ._futures .remove (future )
183+
171184 def _periodic_flush (self , shutdown_event ):
172185 while True :
173186 try :
@@ -207,7 +220,6 @@ def _periodic_retry(self, shutdown_event):
207220
208221 self ._retry_logs .append (RetryableLogs (retry_logs .payload , retry_logs .retries ))
209222
210-
211223 def log_diagnostics_event (self , diagnostics : _Diagnostics ):
212224 event = StatsigEvent (None , _DIAGNOSTICS_EVENT )
213225 event .metadata = diagnostics .serialize ()
0 commit comments