@@ -174,9 +174,10 @@ async def schedule_task(
174
174
The id of the scheduled task
175
175
"""
176
176
status = TaskStatus .SCHEDULED
177
+ start_now = False
177
178
if timestamp is None or timestamp < self ._clock .time_msec ():
178
179
timestamp = self ._clock .time_msec ()
179
- status = TaskStatus . ACTIVE
180
+ start_now = True
180
181
181
182
task = ScheduledTask (
182
183
random_string (16 ),
@@ -190,9 +191,11 @@ async def schedule_task(
190
191
)
191
192
await self ._store .insert_scheduled_task (task )
192
193
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 :
194
197
if self ._run_background_tasks :
195
- await self ._launch_task ( task )
198
+ self ._launch_scheduled_tasks ( )
196
199
else :
197
200
self ._hs .get_replication_command_handler ().send_new_active_task (task .id )
198
201
@@ -300,23 +303,13 @@ async def delete_task(self, id: str) -> None:
300
303
raise Exception (f"Task { id } is currently ACTIVE and can't be deleted" )
301
304
await self ._store .delete_scheduled_task (id )
302
305
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 ()
316
310
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."""
320
313
# Don't bother trying to launch new tasks if we're already at capacity.
321
314
if len (self ._running_tasks ) >= TaskScheduler .MAX_CONCURRENT_RUNNING_TASKS :
322
315
return
@@ -326,20 +319,26 @@ async def _launch_scheduled_tasks(self) -> None:
326
319
327
320
self ._launching_new_tasks = True
328
321
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 )
343
342
344
343
@wrap_as_background_process ("clean_scheduled_tasks" )
345
344
async def _clean_scheduled_tasks (self ) -> None :
0 commit comments