Skip to content

Commit

Permalink
Fix Issue #388: Celery Beat scheduled tasks may be executed repeatedly (
Browse files Browse the repository at this point in the history
#660)

* Fix: The problem that Celery Beat scheduled tasks may be executed repeatedly

* fix: 增加 TypeError 捕获

* fix: Add tests for `test_sync_not_saves_last_run_at_while_schedule_changed`
  • Loading branch information
BaiJiangJie authored Jul 25, 2023
1 parent 5132379 commit 700c804
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 2 deletions.
4 changes: 2 additions & 2 deletions django_celery_beat/schedulers.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,9 +300,9 @@ def sync(self):
while self._dirty:
name = self._dirty.pop()
try:
self.schedule[name].save()
self._schedule[name].save()
_tried.add(name)
except (KeyError, ObjectDoesNotExist):
except (KeyError, TypeError, ObjectDoesNotExist):
_failed.add(name)
except DatabaseError as exc:
logger.exception('Database error while sync: %r', exc)
Expand Down
22 changes: 22 additions & 0 deletions t/unit/test_schedulers.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,28 @@ def test_reserve(self):
assert self.s.flushed == 1
assert self.m2.name in self.s._dirty

def test_sync_not_saves_last_run_at_while_schedule_changed(self):
# Update e1 last_run_at and add to dirty
e1 = self.s.schedule[self.m2.name]
time.sleep(3)
e1.model.last_run_at = e1._default_now()
self.s._dirty.add(e1.model.name)

# Record e1 pre sync last_run_at
e1_pre_sync_last_run_at = e1.model.last_run_at

# Set schedule_changed() == True
self.s._last_timestamp = monotonic()
# Do sync
self.s.sync()

# Record e1 post sync last_run_at
e1_m = PeriodicTask.objects.get(pk=e1.model.pk)
e1_post_sync_last_run_at = e1_m.last_run_at

# Check
assert e1_pre_sync_last_run_at == e1_post_sync_last_run_at

def test_sync_saves_last_run_at(self):
e1 = self.s.schedule[self.m2.name]
last_run = e1.last_run_at
Expand Down

0 comments on commit 700c804

Please sign in to comment.