@@ -32,45 +32,45 @@ def to_tz_aware(time: datetime) -> datetime:
32
32
return time
33
33
34
34
35
- async def schedules_updater (
35
+ async def get_schedules (source : ScheduleSource ) -> List [ScheduledTask ]:
36
+ """
37
+ Get schedules from source.
38
+
39
+ If source raises an exception, it will be
40
+ logged and an empty list will be returned.
41
+
42
+ :param source: source to get schedules from.
43
+ """
44
+ try :
45
+ return await source .get_schedules ()
46
+ except Exception as exc :
47
+ logger .warning (
48
+ "Cannot update schedules with source: %s" ,
49
+ source ,
50
+ )
51
+ logger .debug (exc , exc_info = True )
52
+ return []
53
+
54
+
55
+ async def get_all_schedules (
36
56
scheduler : TaskiqScheduler ,
37
- current_schedules : Dict [ScheduleSource , List [ScheduledTask ]],
38
- event : asyncio .Event ,
39
- ) -> None :
57
+ ) -> Dict [ScheduleSource , List [ScheduledTask ]]:
40
58
"""
41
- Periodic update to schedules.
59
+ Task to update all schedules.
42
60
43
- This task periodically checks for new schedules,
44
- assembles the final list and replaces current
45
- schedule with a new one.
61
+ This function updates all schedules
62
+ from all sources and returns a dict
63
+ with source as a key and list of
64
+ scheduled tasks as a value.
46
65
47
66
:param scheduler: current scheduler.
48
- :param current_schedules: list of schedules.
49
- :param event: event when schedules are updated.
67
+ :return: dict with source as a key and list of scheduled tasks as a value.
50
68
"""
51
- while True :
52
- logger .debug ("Started schedule update." )
53
- new_schedules : "Dict[ScheduleSource, List[ScheduledTask]]" = {}
54
- for source in scheduler .sources :
55
- try :
56
- schedules = await source .get_schedules ()
57
- except Exception as exc :
58
- logger .warning (
59
- "Cannot update schedules with source: %s" ,
60
- source ,
61
- )
62
- logger .debug (exc , exc_info = True )
63
- continue
64
-
65
- new_schedules [source ] = scheduler .merge_func (
66
- new_schedules .get (source ) or [],
67
- schedules ,
68
- )
69
-
70
- current_schedules .clear ()
71
- current_schedules .update (new_schedules )
72
- event .set ()
73
- await asyncio .sleep (scheduler .refresh_delay )
69
+ logger .debug ("Started schedule update." )
70
+ schedules = await asyncio .gather (
71
+ * [get_schedules (source ) for source in scheduler .sources ],
72
+ )
73
+ return dict (zip (scheduler .sources , schedules ))
74
74
75
75
76
76
def get_task_delay (task : ScheduledTask ) -> Optional [int ]:
@@ -141,23 +141,14 @@ async def run_scheduler_loop(scheduler: TaskiqScheduler) -> None:
141
141
:param scheduler: current scheduler.
142
142
"""
143
143
loop = asyncio .get_event_loop ()
144
- schedules : "Dict[ScheduleSource, List[ScheduledTask]]" = {}
145
-
146
- current_task = asyncio .current_task ()
147
- first_update_event = asyncio .Event ()
148
- updater_task = loop .create_task (
149
- schedules_updater (
150
- scheduler ,
151
- schedules ,
152
- first_update_event ,
153
- ),
154
- )
155
- if current_task is not None :
156
- current_task .add_done_callback (lambda _ : updater_task .cancel ())
157
- await first_update_event .wait ()
158
144
running_schedules = set ()
159
145
while True :
160
- for source , task_list in schedules .items ():
146
+ # We use this method to correctly sleep for one minute.
147
+ next_minute = datetime .now ().replace (second = 0 , microsecond = 0 ) + timedelta (
148
+ minutes = 1 ,
149
+ )
150
+ scheduled_tasks = await get_all_schedules (scheduler )
151
+ for source , task_list in scheduled_tasks .items ():
161
152
for task in task_list :
162
153
try :
163
154
task_delay = get_task_delay (task )
@@ -175,11 +166,7 @@ async def run_scheduler_loop(scheduler: TaskiqScheduler) -> None:
175
166
running_schedules .add (send_task )
176
167
send_task .add_done_callback (running_schedules .discard )
177
168
178
- delay = (
179
- datetime .now ().replace (second = 1 , microsecond = 0 )
180
- + timedelta (minutes = 1 )
181
- - datetime .now ()
182
- )
169
+ delay = next_minute - datetime .now ()
183
170
await asyncio .sleep (delay .total_seconds ())
184
171
185
172
0 commit comments