From e3fef5b22671ef853470f034468475f2f89b9b11 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 17 Oct 2023 16:05:43 +1100 Subject: [PATCH] Improve checks for scheduled tasks at startup (#5724) - Only update or create tasks if necessary - Perform bulk_create and bulk_update operations - Reduce to N(1) - independent of how many tasks we add in the future Ref: https://github.com/inventree/InvenTree/issues/5586 --- InvenTree/InvenTree/apps.py | 46 +++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/InvenTree/InvenTree/apps.py b/InvenTree/InvenTree/apps.py index 2aff4d6823..dbc45b85d4 100644 --- a/InvenTree/InvenTree/apps.py +++ b/InvenTree/InvenTree/apps.py @@ -82,16 +82,52 @@ class InvenTreeConfig(AppConfig): logger.info("Starting background tasks...") + from django_q.models import Schedule + + # List of existing scheduled tasks (in the database) + existing_tasks = {} + + for existing_task in Schedule.objects.all(): + existing_tasks[existing_task.func] = existing_task + + tasks_to_create = [] + tasks_to_update = [] + # List of collected tasks found with the @scheduled_task decorator tasks = InvenTree.tasks.tasks.task_list for task in tasks: + ref_name = f'{task.func.__module__}.{task.func.__name__}' - InvenTree.tasks.schedule_task( - ref_name, - schedule_type=task.interval, - minutes=task.minutes, - ) + + if ref_name in existing_tasks.keys(): + # This task already exists - update the details if required + existing_task = existing_tasks[ref_name] + + if existing_task.schedule_type != task.interval or existing_task.minutes != task.minutes: + + existing_task.schedule_type = task.interval + existing_task.minutes = task.minutes + tasks_to_update.append(existing_task) + + else: + # This task does *not* already exist - create it + tasks_to_create.append( + Schedule( + name=ref_name, + func=ref_name, + schedule_type=task.interval, + minutes=task.minutes, + ) + ) + + if len(tasks_to_create) > 0: + Schedule.objects.bulk_create(tasks_to_create) + logger.info("Created %s new scheduled tasks", len(tasks_to_create)) + + if len(tasks_to_update) > 0: + Schedule.objects.bulk_update(tasks_to_update, ['schedule_type', 'minutes']) + logger.info("Updated %s existing scheduled tasks", len(tasks_to_update)) # Put at least one task onto the background worker stack, # which will be processed as soon as the worker comes online