Skip to content

Commit 2f87bb2

Browse files
tinylambdaauvipy
authored andcommitted
After changing the PeriodicTask for one-off task we should mark it ch… (#185)
* After changing the PeriodicTask for one-off task we should mark it changed to update the runtime scheduled tasks * is_due should return schedules.schedstate to be consistent with celery's implementation * add test case : test_heap_always_return_the_first_item * fix flake8 error * fix flake8 error
1 parent 1bcf81b commit 2f87bb2

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

django_celery_beat/schedulers.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,22 +98,25 @@ def _disable(self, model):
9898

9999
def is_due(self):
100100
if not self.model.enabled:
101-
return False, 5.0 # 5 second delay for re-enable.
101+
# 5 second delay for re-enable.
102+
return schedules.schedstate(False, 5.0)
102103

103104
# START DATE: only run after the `start_time`, if one exists.
104105
if self.model.start_time is not None:
105106
if maybe_make_aware(self._default_now()) < self.model.start_time:
106107
# The datetime is before the start date - don't run.
107108
_, delay = self.schedule.is_due(self.last_run_at)
108-
return False, delay # use original delay for re-check
109+
# use original delay for re-check
110+
return schedules.schedstate(False, delay)
109111

110112
# ONE OFF TASK: Disable one off tasks after they've ran once
111113
if self.model.one_off and self.model.enabled \
112114
and self.model.total_run_count > 0:
113115
self.model.enabled = False
114116
self.model.total_run_count = 0 # Reset
117+
self.model.no_changes = False # Mark the model entry as changed
115118
self.model.save()
116-
return False, None # Don't recheck
119+
return schedules.schedstate(False, None) # Don't recheck
117120

118121
return self.schedule.is_due(self.last_run_at)
119122

t/unit/test_schedulers.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import absolute_import, unicode_literals
22

3+
import time
34
import pytest
45

56
from datetime import datetime, timedelta
@@ -422,6 +423,40 @@ def test_scheduler_schedules_equality_on_change(self, monkeypatch):
422423
monkeypatch.setattr(self.s, 'schedule_changed', lambda: True)
423424
assert not self.s.schedules_equal(self.s.schedule, self.s.schedule)
424425

426+
def test_heap_always_return_the_first_item(self):
427+
interval = 10
428+
429+
s1 = schedule(timedelta(seconds=interval))
430+
m1 = self.create_model_interval(s1, enabled=False)
431+
m1.last_run_at = self.app.now() - timedelta(seconds=interval + 2)
432+
m1.save()
433+
m1.refresh_from_db()
434+
435+
s2 = schedule(timedelta(seconds=interval))
436+
m2 = self.create_model_interval(s2, enabled=True)
437+
m2.last_run_at = self.app.now() - timedelta(seconds=interval + 1)
438+
m2.save()
439+
m2.refresh_from_db()
440+
441+
e1 = EntryTrackSave(m1, self.app)
442+
# because the disabled task e1 runs first, e2 will never be executed
443+
e2 = EntryTrackSave(m2, self.app)
444+
445+
s = self.Scheduler(app=self.app)
446+
s.schedule.clear()
447+
s.schedule[e1.name] = e1
448+
s.schedule[e2.name] = e2
449+
450+
tried = set()
451+
for _ in range(len(s.schedule) * 8):
452+
tick_interval = s.tick()
453+
if tick_interval and tick_interval > 0.0:
454+
tried.add(s._heap[0].entry.name)
455+
time.sleep(tick_interval)
456+
if s.should_sync():
457+
s.sync()
458+
assert len(tried) == 1 and tried == set([e1.name])
459+
425460

426461
@pytest.mark.django_db()
427462
class test_models(SchedulerCase):

0 commit comments

Comments
 (0)