From 476be260ab4a2545fe1adc0f260e630c6e50e8bd Mon Sep 17 00:00:00 2001 From: chentt <7448203+daydaychen@users.noreply.github.com> Date: Thu, 7 Nov 2024 20:09:52 +0800 Subject: [PATCH] fix long period task will never be triggered (#717) * fix long period task will never be triggered * fix (schedulers): when model.date_changed is None, use _default.now() * test (schedulers): add test for when model.last_run_at is None * test (scheduler): revise the comment --------- Co-authored-by: chentiantian --- django_celery_beat/schedulers.py | 2 +- t/unit/test_schedulers.py | 49 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/django_celery_beat/schedulers.py b/django_celery_beat/schedulers.py index a73faff3..ce46b661 100644 --- a/django_celery_beat/schedulers.py +++ b/django_celery_beat/schedulers.py @@ -84,7 +84,7 @@ def __init__(self, model, app=None): self.model = model if not model.last_run_at: - model.last_run_at = self._default_now() + model.last_run_at = model.date_changed or self._default_now() # if last_run_at is not set and # model.start_time last_run_at should be in way past. # This will trigger the job to run at start_time diff --git a/t/unit/test_schedulers.py b/t/unit/test_schedulers.py index f7889c77..544ac4bd 100644 --- a/t/unit/test_schedulers.py +++ b/t/unit/test_schedulers.py @@ -213,6 +213,55 @@ def test_entry_and_model_last_run_at_with_utc_no_use_tz(self, monkeypatch): if hasattr(time, "tzset"): time.tzset() + @override_settings( + USE_TZ=False, + DJANGO_CELERY_BEAT_TZ_AWARE=False + ) + @pytest.mark.usefixtures('depends_on_current_app') + @timezone.override('Europe/Berlin') + @pytest.mark.celery(timezone='Europe/Berlin') + def test_entry_and_model_last_run_at_when_model_changed(self, monkeypatch): + old_tz = os.environ.get("TZ") + os.environ["TZ"] = "Europe/Berlin" + if hasattr(time, "tzset"): + time.tzset() + assert self.app.timezone.key == 'Europe/Berlin' + # simulate last_run_at from DB - not TZ aware but localtime + right_now = datetime.utcnow() + # make sure to use fixed date time + monkeypatch.setattr(self.Entry, '_default_now', lambda o: right_now) + m = self.create_model_crontab( + crontab(minute='*/10') + ) + m.save() + e = self.Entry(m, app=self.app) + e.save() + m.refresh_from_db() + + # The just created model has no value for date_changed + # so last_run_at should be set to the Entry._default_now() + assert m.last_run_at == e.last_run_at + + # If the model has been updated and the entry.last_run_at is None, + # entry.last_run_at should be set to the value of model.date_changed. + # see #717 + m2 = self.create_model_crontab( + crontab(minute='*/10') + ) + m2.save() + m2.refresh_from_db() + assert m2.date_changed is not None + e2 = self.Entry(m2, app=self.app) + e2.save() + assert m2.last_run_at == m2.date_changed + + if old_tz is not None: + os.environ["TZ"] = old_tz + else: + del os.environ["TZ"] + if hasattr(time, "tzset"): + time.tzset() + @override_settings( USE_TZ=False, DJANGO_CELERY_BEAT_TZ_AWARE=False,