From 8026f74e802dc6be07f694af9801363bf4c5bcf3 Mon Sep 17 00:00:00 2001 From: Justin Hynes Date: Fri, 20 May 2022 10:30:06 -0400 Subject: [PATCH] feat: Add management command for processing scheduled instructor tasks [MICROBA-1512] * Adds a new management command to the `instructor_task` app that will be used to process scheduled tasks ready for execution by Celery. --- lms/djangoapps/instructor_task/api.py | 3 ++- lms/djangoapps/instructor_task/api_helper.py | 2 +- .../commands/process_scheduled_instructor_tasks.py | 14 ++++++++++++++ lms/djangoapps/instructor_task/tests/test_api.py | 6 +++--- .../instructor_task/tests/test_api_helper.py | 2 +- 5 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 lms/djangoapps/instructor_task/management/commands/process_scheduled_instructor_tasks.py diff --git a/lms/djangoapps/instructor_task/api.py b/lms/djangoapps/instructor_task/api.py index dbf87ea030..03c4d29b0a 100644 --- a/lms/djangoapps/instructor_task/api.py +++ b/lms/djangoapps/instructor_task/api.py @@ -575,13 +575,14 @@ def generate_anonymous_ids(request, course_key): return submit_task(request, task_type, task_class, course_key, task_input, task_key) -def process_scheduled_tasks(): +def process_scheduled_instructor_tasks(): """ Utility function that retrieves tasks whose schedules have elapsed and should be processed. Only retrieves instructor tasks that are in the `SCHEDULED` state. Then submits these tasks for processing by Celery. """ now = datetime.datetime.now(pytz.utc) due_schedules = InstructorTaskSchedule.objects.filter(task__task_state=SCHEDULED).filter(task_due__lte=now) + log.info(f"Retrieved {due_schedules.count()} scheduled instructor tasks due for execution") for schedule in due_schedules: try: log.info(f"Attempting to queue scheduled task with id '{schedule.task.id}'") diff --git a/lms/djangoapps/instructor_task/api_helper.py b/lms/djangoapps/instructor_task/api_helper.py index 06e09372a0..b346b9700d 100644 --- a/lms/djangoapps/instructor_task/api_helper.py +++ b/lms/djangoapps/instructor_task/api_helper.py @@ -526,7 +526,7 @@ def submit_scheduled_task(schedule): # turn this into the format Celery expects task_args = [schedule.task.id, task_arguments] # submit the task - log.info(f"Submitting scheduled task {schedule.task.id} for processing") + log.info(f"Submitting scheduled task '{schedule.task.id}' for processing") task_class.apply_async(task_args, task_id=schedule.task.task_id) except Exception as error: # pylint: disable=broad-except # broad except here to make sure we cast a wide net for tasks with issues that can't be processed diff --git a/lms/djangoapps/instructor_task/management/commands/process_scheduled_instructor_tasks.py b/lms/djangoapps/instructor_task/management/commands/process_scheduled_instructor_tasks.py new file mode 100644 index 0000000000..ad93dda09a --- /dev/null +++ b/lms/djangoapps/instructor_task/management/commands/process_scheduled_instructor_tasks.py @@ -0,0 +1,14 @@ +""" +Command to process scheduled instructor tasks. +""" +from django.core.management.base import BaseCommand + +from lms.djangoapps.instructor_task.api import process_scheduled_instructor_tasks + + +class Command(BaseCommand): + """ + Command to process Instructor Tasks in the `SCHEDULED` state that are due for execution. + """ + def handle(self, *args, **options): + process_scheduled_instructor_tasks() diff --git a/lms/djangoapps/instructor_task/tests/test_api.py b/lms/djangoapps/instructor_task/tests/test_api.py index f8f8465db6..79d2184582 100644 --- a/lms/djangoapps/instructor_task/tests/test_api.py +++ b/lms/djangoapps/instructor_task/tests/test_api.py @@ -28,7 +28,7 @@ from lms.djangoapps.instructor_task.api import ( generate_certificates_for_students, get_instructor_task_history, get_running_instructor_tasks, - process_scheduled_tasks, + process_scheduled_instructor_tasks, regenerate_certificates, submit_bulk_course_email, submit_calculate_may_enroll_csv, @@ -508,7 +508,7 @@ class InstructorTaskCourseSubmitTest(TestReportMixin, InstructorTaskCourseTestCa ] with LogCapture() as log: - process_scheduled_tasks() + process_scheduled_instructor_tasks() mock_submit_scheduled_task.assert_called_once_with(due_instructor_task_schedule) log.check_present((LOG_PATH, "INFO", expected_messages[0]),) @@ -528,7 +528,7 @@ class InstructorTaskCourseSubmitTest(TestReportMixin, InstructorTaskCourseTestCa ] with LogCapture() as log: - process_scheduled_tasks() + process_scheduled_instructor_tasks() log.check_present((LOG_PATH, "ERROR", expected_messages[0]),) diff --git a/lms/djangoapps/instructor_task/tests/test_api_helper.py b/lms/djangoapps/instructor_task/tests/test_api_helper.py index 6426388ca7..45df5a241a 100644 --- a/lms/djangoapps/instructor_task/tests/test_api_helper.py +++ b/lms/djangoapps/instructor_task/tests/test_api_helper.py @@ -185,7 +185,7 @@ class ScheduledInstructorTaskSubmissionTests(InstructorTaskCourseTestCase): expected_task_arguments = json.loads(schedule.task_args) expected_task_args = [schedule.task.id, expected_task_arguments] expected_messages = [ - f"Submitting scheduled task {schedule.task.id} for processing", + f"Submitting scheduled task '{schedule.task.id}' for processing", ] with LogCapture() as log: