Skip to content

Commit 28ba977

Browse files
yang.yuauvipy
authored andcommitted
fix: fix clock schedule and one off task stuck
1 parent 7d9069c commit 28ba977

File tree

7 files changed

+36
-51
lines changed

7 files changed

+36
-51
lines changed

django_celery_beat/admin.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,14 +245,9 @@ class ClockedScheduleAdmin(admin.ModelAdmin):
245245

246246
fields = (
247247
'clocked_time',
248-
'enabled',
249-
)
250-
readonly_fields = (
251-
'enabled',
252248
)
253249
list_display = (
254250
'clocked_time',
255-
'enabled',
256251
)
257252

258253

django_celery_beat/clockedschedule.py

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@
22

33
from celery import schedules
44
from celery.utils.time import maybe_make_aware
5-
from collections import namedtuple
6-
7-
try:
8-
from celery.schedules import schedstate # Celery >=3.1.0
9-
except ImportError:
10-
schedstate = namedtuple('schedstate', ('is_due', 'next'))
5+
from .utils import NEVER_CHECK_TIMEOUT
116

127

138
class clocked(schedules.BaseSchedule):
@@ -16,36 +11,27 @@ class clocked(schedules.BaseSchedule):
1611
Depends on PeriodicTask one_off=True
1712
"""
1813

19-
def __init__(self, clocked_time, enabled=True,
20-
model=None, nowfun=None, app=None):
14+
def __init__(self, clocked_time, nowfun=None, app=None):
2115
"""Initialize clocked."""
2216
self.clocked_time = maybe_make_aware(clocked_time)
23-
self.enabled = enabled
24-
self.model = model
2517
super(clocked, self).__init__(nowfun=nowfun, app=app)
2618

2719
def remaining_estimate(self, last_run_at):
2820
return self.clocked_time - self.now()
2921

3022
def is_due(self, last_run_at):
31-
if not self.enabled:
32-
return schedstate(is_due=False, next=None)
3323
rem_delta = self.remaining_estimate(None)
3424
remaining_s = max(rem_delta.total_seconds(), 0)
3525
if remaining_s == 0:
36-
if self.model:
37-
self.model.enabled = False
38-
self.model.save()
39-
return schedstate(is_due=True, next=None)
40-
return schedstate(is_due=False, next=remaining_s)
26+
return schedules.schedstate(is_due=True, next=NEVER_CHECK_TIMEOUT)
27+
return schedules.schedstate(is_due=False, next=remaining_s)
4128

4229
def __repr__(self):
43-
return '<clocked: {} {}>'.format(self.clocked_time, self.enabled)
30+
return '<clocked: {}>'.format(self.clocked_time)
4431

4532
def __eq__(self, other):
4633
if isinstance(other, clocked):
47-
return self.clocked_time == other.clocked_time and \
48-
self.enabled == other.enabled
34+
return self.clocked_time == other.clocked_time
4935
return False
5036

5137
def __ne__(self, other):
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 2.2.4 on 2019-08-30 00:46
2+
# flake8: noqa
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('django_celery_beat', '0013_auto_20200609_0727'),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name='clockedschedule',
15+
name='enabled',
16+
),
17+
]

django_celery_beat/models.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,6 @@ class ClockedSchedule(models.Model):
201201
verbose_name=_('Clock Time'),
202202
help_text=_('Run the task at clocked time'),
203203
)
204-
enabled = models.BooleanField(
205-
default=True,
206-
editable=False,
207-
verbose_name=_('Enabled'),
208-
help_text=_('Set to False to disable the schedule'),
209-
)
210204

211205
class Meta:
212206
"""Table information."""
@@ -216,18 +210,16 @@ class Meta:
216210
ordering = ['clocked_time']
217211

218212
def __str__(self):
219-
return '{} {}'.format(self.clocked_time, self.enabled)
213+
return '{}'.format(self.clocked_time)
220214

221215
@property
222216
def schedule(self):
223-
c = clocked(clocked_time=self.clocked_time,
224-
enabled=self.enabled, model=self)
217+
c = clocked(clocked_time=self.clocked_time)
225218
return c
226219

227220
@classmethod
228221
def from_schedule(cls, schedule):
229-
spec = {'clocked_time': schedule.clocked_time,
230-
'enabled': schedule.enabled}
222+
spec = {'clocked_time': schedule.clocked_time}
231223
try:
232224
return cls.objects.get(**spec)
233225
except cls.DoesNotExist:

django_celery_beat/schedulers.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
SolarSchedule, ClockedSchedule
2525
)
2626
from .clockedschedule import clocked
27+
from .utils import NEVER_CHECK_TIMEOUT
2728

2829
try:
2930
from celery.utils.time import is_naive
@@ -128,7 +129,8 @@ def is_due(self):
128129
self.model.total_run_count = 0 # Reset
129130
self.model.no_changes = False # Mark the model entry as changed
130131
self.model.save()
131-
return schedules.schedstate(False, None) # Don't recheck
132+
# Don't recheck
133+
return schedules.schedstate(False, NEVER_CHECK_TIMEOUT)
132134

133135
# CAUTION: make_aware assumes settings.TIME_ZONE for naive datetimes,
134136
# while maybe_make_aware assumes utc for naive datetimes

django_celery_beat/utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from django.utils import timezone
66

77
is_aware = timezone.is_aware
8+
# celery schedstate return None will make it not work
9+
NEVER_CHECK_TIMEOUT = 100000000
810

911
# see Issue #222
1012
now_localtime = getattr(timezone, 'template_localtime', timezone.localtime)

t/unit/test_schedulers.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
PeriodicTask, PeriodicTasks, IntervalSchedule, CrontabSchedule,
2222
SolarSchedule, ClockedSchedule, DAYS
2323
)
24-
from django_celery_beat.utils import make_aware
24+
from django_celery_beat.utils import make_aware, NEVER_CHECK_TIMEOUT
2525

2626
_ids = count(0)
2727

@@ -288,7 +288,7 @@ def test_one_off_task(self):
288288
e2 = self.Entry(m2, app=self.app)
289289
isdue, delay = e2.is_due()
290290
assert not isdue
291-
assert delay is None
291+
assert delay == NEVER_CHECK_TIMEOUT
292292

293293

294294
@pytest.mark.django_db()
@@ -638,8 +638,8 @@ def test_PeriodicTask_unicode_clocked(self):
638638
p = self.create_model_clocked(
639639
clocked(time), name='clocked_event'
640640
)
641-
assert str(p) == '{0}: {1} {2}'.format(
642-
'clocked_event', str(time), True
641+
assert str(p) == '{0}: {1}'.format(
642+
'clocked_event', str(time)
643643
)
644644

645645
def test_PeriodicTask_schedule_property(self):
@@ -743,16 +743,7 @@ def test_ClockedSchedule_schedule(self):
743743
assert s.schedule is not None
744744
isdue2, nextcheck2 = s.schedule.is_due(dt2_lastrun)
745745
assert isdue2 is True # True means task is due and should run.
746-
assert (nextcheck2 is None) and (isdue2 is True)
747-
print(s.schedule.enabled)
748-
749-
assert s.schedule is not None
750-
isdue3, nextcheck3 = s.schedule.is_due(dt2_lastrun)
751-
print(s.schedule.clocked_time, s.schedule.enabled)
752-
print(isdue3, nextcheck3)
753-
# False means task isn't due, but keep checking.
754-
assert isdue3 is False
755-
assert (nextcheck3 is None) and (isdue3 is False)
746+
assert (nextcheck2 == NEVER_CHECK_TIMEOUT) and (isdue2 is True)
756747

757748

758749
@pytest.mark.django_db()

0 commit comments

Comments
 (0)