1+ import asyncio
2+ import threading
3+ import time
4+
5+
6+ class BackgroundClient :
7+
8+ def __init__ (self , format , transport , period = 15.0 , * args , ** kwargs ):
9+ self .format = format
10+ self .transport = transport
11+ self .period = float (period )
12+ self .stop_event = None
13+
14+ self ._period_step = 0.5 # check event every 0.5 seconds
15+
16+ super ().__init__ (* args , ** kwargs )
17+
18+ def sleep_steps_iter (self , period ):
19+ n_full_steps , last_step = divmod (period , self ._period_step )
20+ for _ in range (int (n_full_steps )):
21+ yield self ._period_step
22+ if last_step > 0 :
23+ yield last_step
24+
25+
26+ class ThreadBGClient (BackgroundClient , threading .Thread ):
27+ def start (self ):
28+ self .stop_event = threading .Event ()
29+ self .transport .start ()
30+ super ().start ()
31+
32+ def stop (self ):
33+ self .stop_event .set ()
34+ self .join ()
35+ self .transport .stop ()
36+
37+ def run (self ):
38+ period = self .period
39+
40+ while not self .stop_event .is_set ():
41+ for step in self .sleep_steps_iter (period ):
42+ time .sleep (step )
43+ if self .stop_event .is_set ():
44+ break
45+
46+ ts_start = time .time ()
47+ samples_iter = self .format .iter_samples ()
48+ try :
49+ self .transport .push_all (samples_iter )
50+ except Exception :
51+ pass # TODO log?
52+ period = self .period - (time .time () - ts_start )
53+
54+
55+ class AsyncioBGClient (BackgroundClient ):
56+ async def start (self ):
57+ self .stop_event = asyncio .Event ()
58+ await self .transport .start ()
59+ self ._runner = asyncio .create_task (self .run ())
60+
61+ async def stop (self ):
62+ self .stop_event .set ()
63+ await asyncio .wait ([self ._runner ]) # TODO timeout, catch errors
64+ self .transport .stop ()
65+
66+ async def run (self ):
67+ period = self .period
68+
69+ while not self .stop_event .is_set ():
70+ for step in self .sleep_steps_iter (period ):
71+ try :
72+ await asyncio .sleep (step )
73+ except asyncio .CancelledError :
74+ self .stop_event .set ()
75+ if self .stop_event .is_set ():
76+ break
77+
78+ ts_start = time .time ()
79+ samples_iter = self .format .iter_samples ()
80+ try :
81+ await self .transport .push_all (samples_iter )
82+ except Exception :
83+ pass # TODO: log?
84+ period = self .period - (time .time () - ts_start )
0 commit comments