Skip to content

Commit 874fc84

Browse files
committed
Fix CrontabSchedule task run before schedule time
1 parent 0bac717 commit 874fc84

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

django_celery_beat/schedulers.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,19 @@ def __init__(self, model, app=None):
9494

9595
if not model.last_run_at:
9696
model.last_run_at = model.date_changed or self._default_now()
97-
# if last_run_at is not set and
98-
# model.start_time last_run_at should be in way past.
99-
# This will trigger the job to run at start_time
100-
# and avoid the heap block.
97+
10198
if self.model.start_time:
102-
model.last_run_at = model.last_run_at \
103-
- datetime.timedelta(days=365 * 30)
99+
if isinstance(model.schedule, schedules.schedule):
100+
# if last_run_at is not set and
101+
# model.start_time last_run_at should be in way past.
102+
# This will trigger the job to run at start_time
103+
# and avoid the heap block.
104+
model.last_run_at = model.last_run_at \
105+
- datetime.timedelta(days=365 * 30)
106+
else:
107+
# last_run_at should be the time the task started.
108+
model.last_run_at = model.start_time
109+
104110

105111
self.last_run_at = model.last_run_at
106112

t/unit/test_schedulers.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,24 @@ def test_crontab_with_start_time_after_crontab(self, app):
10351035
assert not is_due
10361036
assert next_check == pytest.approx(expected_delay, abs=60)
10371037

1038+
def test_crontab_with_start_time_before_crontab(self, app):
1039+
now = app.now()
1040+
delay_minutes = 2
1041+
test_start_time = now - timedelta(minutes=delay_minutes)
1042+
crontab_time = now + timedelta(minutes=delay_minutes)
1043+
1044+
# start_time(now - 2min) < now < crontab_time(now + 2min)
1045+
task = self.create_model_crontab(
1046+
crontab(minute=f'{crontab_time.minute}'),
1047+
start_time=test_start_time)
1048+
1049+
entry = EntryTrackSave(task, app=app)
1050+
is_due, next_check = entry.is_due()
1051+
1052+
expected_delay = delay_minutes * 60
1053+
assert not is_due
1054+
assert next_check < expected_delay
1055+
10381056
def test_crontab_with_start_time_different_time_zone(self, app):
10391057
now = app.now()
10401058

0 commit comments

Comments
 (0)