From a154fd658a240db354810e997e81b0fa940dcc32 Mon Sep 17 00:00:00 2001 From: Fernando Karchiloff Date: Wed, 12 Mar 2025 19:31:00 -0300 Subject: [PATCH] Avoid creating task run on Scheduler creation (#268) --- django_q/models.py | 6 +++++ django_q/tests/test_scheduler.py | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/django_q/models.py b/django_q/models.py index 69dd5bb..5cc534f 100644 --- a/django_q/models.py +++ b/django_q/models.py @@ -302,6 +302,12 @@ class Schedule(models.Model): def __str__(self): return self.func + def save(self, *args, **kwargs): + if self.pk is None and self.schedule_type == self.CRON: + self.next_run = self.calculate_next_run() + + return super().save(*args, **kwargs) + success.boolean = True success.short_description = _("success") last_run.allow_tags = True diff --git a/django_q/tests/test_scheduler.py b/django_q/tests/test_scheduler.py index edecf53..fcad6f8 100644 --- a/django_q/tests/test_scheduler.py +++ b/django_q/tests/test_scheduler.py @@ -473,6 +473,47 @@ def test_scheduler_atomic_must_specify_the_database_based_on_router_redirection( mocked_db.atomic.assert_called_with(using="default") +@pytest.mark.django_db +def test_schedule_save_sets_next_run_for_cron(): + """Ensure Schedule.save() sets next_run correctly for CRON schedules.""" + cron_expression = "0 12 * * *" # Executes dialy at 12pm + schedule = Schedule( + func="math.sqrt", + schedule_type=Schedule.CRON, + cron=cron_expression, + ) + + assert schedule.next_run is not None + assert schedule.pk is None + + initial_next_run = schedule.next_run + schedule.save() + + # After save, next_run must be recalculated based on the CRON expression + assert schedule.next_run > initial_next_run + + +@pytest.mark.django_db +def test_schedule_save_direct_db(broker): + """Ensure Schedule.save() updates next_run correctly when created directly in DB.""" + cron_expression = "0 12 * * *" # Executes dialy at 12pm + + # Creating schedule directly in database + schedule = Schedule.objects.create( + func="math.sqrt", + schedule_type=Schedule.CRON, + cron=cron_expression, + ) + + # Next run must be defined after execution time + assert schedule.next_run is not None + assert schedule.next_run > timezone.now() + + scheduler(broker) + + assert broker.queue_size() == 0 + + def test_localtime(): assert not is_naive(localtime())