@@ -174,9 +174,10 @@ async def schedule_task(
174174 The id of the scheduled task
175175 """
176176 status = TaskStatus .SCHEDULED
177+ start_now = False
177178 if timestamp is None or timestamp < self ._clock .time_msec ():
178179 timestamp = self ._clock .time_msec ()
179- status = TaskStatus . ACTIVE
180+ start_now = True
180181
181182 task = ScheduledTask (
182183 random_string (16 ),
@@ -190,9 +191,11 @@ async def schedule_task(
190191 )
191192 await self ._store .insert_scheduled_task (task )
192193
193- if status == TaskStatus .ACTIVE :
194+ # If the task is ready to run immediately, run the scheduling algorithm now
195+ # rather than waiting
196+ if start_now :
194197 if self ._run_background_tasks :
195- await self ._launch_task ( task )
198+ self ._launch_scheduled_tasks ( )
196199 else :
197200 self ._hs .get_replication_command_handler ().send_new_active_task (task .id )
198201
@@ -300,23 +303,13 @@ async def delete_task(self, id: str) -> None:
300303 raise Exception (f"Task { id } is currently ACTIVE and can't be deleted" )
301304 await self ._store .delete_scheduled_task (id )
302305
303- def launch_task_by_id (self , id : str ) -> None :
304- """Try launching the task with the given ID."""
305- # Don't bother trying to launch new tasks if we're already at capacity.
306- if len (self ._running_tasks ) >= TaskScheduler .MAX_CONCURRENT_RUNNING_TASKS :
307- return
308-
309- run_as_background_process ("launch_task_by_id" , self ._launch_task_by_id , id )
310-
311- async def _launch_task_by_id (self , id : str ) -> None :
312- """Helper async function for `launch_task_by_id`."""
313- task = await self .get_task (id )
314- if task :
315- await self ._launch_task (task )
306+ def on_new_task (self , task_id : str ) -> None :
307+ """Handle a notification that a new ready-to-run task has been added to the queue"""
308+ # Just run the scheduler
309+ self ._launch_scheduled_tasks ()
316310
317- @wrap_as_background_process ("launch_scheduled_tasks" )
318- async def _launch_scheduled_tasks (self ) -> None :
319- """Retrieve and launch scheduled tasks that should be running at that time."""
311+ def _launch_scheduled_tasks (self ) -> None :
312+ """Retrieve and launch scheduled tasks that should be running at this time."""
320313 # Don't bother trying to launch new tasks if we're already at capacity.
321314 if len (self ._running_tasks ) >= TaskScheduler .MAX_CONCURRENT_RUNNING_TASKS :
322315 return
@@ -326,20 +319,26 @@ async def _launch_scheduled_tasks(self) -> None:
326319
327320 self ._launching_new_tasks = True
328321
329- try :
330- for task in await self .get_tasks (
331- statuses = [TaskStatus .ACTIVE ], limit = self .MAX_CONCURRENT_RUNNING_TASKS
332- ):
333- await self ._launch_task (task )
334- for task in await self .get_tasks (
335- statuses = [TaskStatus .SCHEDULED ],
336- max_timestamp = self ._clock .time_msec (),
337- limit = self .MAX_CONCURRENT_RUNNING_TASKS ,
338- ):
339- await self ._launch_task (task )
340-
341- finally :
342- self ._launching_new_tasks = False
322+ async def inner () -> None :
323+ try :
324+ for task in await self .get_tasks (
325+ statuses = [TaskStatus .ACTIVE ],
326+ limit = self .MAX_CONCURRENT_RUNNING_TASKS ,
327+ ):
328+ # _launch_task will ignore tasks that we're already running, and
329+ # will also do nothing if we're already at the maximum capacity.
330+ await self ._launch_task (task )
331+ for task in await self .get_tasks (
332+ statuses = [TaskStatus .SCHEDULED ],
333+ max_timestamp = self ._clock .time_msec (),
334+ limit = self .MAX_CONCURRENT_RUNNING_TASKS ,
335+ ):
336+ await self ._launch_task (task )
337+
338+ finally :
339+ self ._launching_new_tasks = False
340+
341+ run_as_background_process ("launch_scheduled_tasks" , inner )
343342
344343 @wrap_as_background_process ("clean_scheduled_tasks" )
345344 async def _clean_scheduled_tasks (self ) -> None :
0 commit comments