@@ -32,45 +32,45 @@ def to_tz_aware(time: datetime) -> datetime:
3232 return time
3333
3434
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 (
3656 scheduler : TaskiqScheduler ,
37- current_schedules : Dict [ScheduleSource , List [ScheduledTask ]],
38- event : asyncio .Event ,
39- ) -> None :
57+ ) -> Dict [ScheduleSource , List [ScheduledTask ]]:
4058 """
41- Periodic update to schedules.
59+ Task to update all schedules.
4260
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.
4665
4766 :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.
5068 """
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 ))
7474
7575
7676def get_task_delay (task : ScheduledTask ) -> Optional [int ]:
@@ -141,23 +141,14 @@ async def run_scheduler_loop(scheduler: TaskiqScheduler) -> None:
141141 :param scheduler: current scheduler.
142142 """
143143 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 ()
158144 running_schedules = set ()
159145 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 ():
161152 for task in task_list :
162153 try :
163154 task_delay = get_task_delay (task )
@@ -175,11 +166,7 @@ async def run_scheduler_loop(scheduler: TaskiqScheduler) -> None:
175166 running_schedules .add (send_task )
176167 send_task .add_done_callback (running_schedules .discard )
177168
178- delay = (
179- datetime .now ().replace (second = 1 , microsecond = 0 )
180- + timedelta (minutes = 1 )
181- - datetime .now ()
182- )
169+ delay = next_minute - datetime .now ()
183170 await asyncio .sleep (delay .total_seconds ())
184171
185172
0 commit comments