Skip to content

Commit cf523b0

Browse files
committed
fix:repeatable task without start date #276
1 parent 6ae0b16 commit cf523b0

File tree

2 files changed

+37
-19
lines changed

2 files changed

+37
-19
lines changed

scheduler/models/task.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,9 @@ def is_scheduled(self) -> bool:
187187
return False
188188
# check whether job_id is in scheduled/queued/active jobs
189189
res = (
190-
(self.job_name in self.rqueue.scheduled_job_registry.all())
191-
or (self.job_name in self.rqueue.queued_job_registry.all())
192-
or (self.job_name in self.rqueue.active_job_registry.all())
190+
(self.job_name in self.rqueue.scheduled_job_registry.all())
191+
or (self.job_name in self.rqueue.queued_job_registry.all())
192+
or (self.job_name in self.rqueue.active_job_registry.all())
193193
)
194194
# If the job_id is not scheduled/queued/started,
195195
# update the job_id to None. (The job_id belongs to a previous run which is completed)
@@ -360,6 +360,7 @@ def _schedule(self) -> bool:
360360
return True
361361

362362
def save(self, **kwargs):
363+
self.clean()
363364
schedule_job = kwargs.pop("schedule_job", True)
364365
update_fields = kwargs.get("update_fields", None)
365366
if update_fields is not None:
@@ -406,7 +407,7 @@ def clean_interval_unit(self):
406407
code="invalid",
407408
params={"queue": self.queue, "interval": config.SCHEDULER_INTERVAL},
408409
)
409-
if self.interval_seconds() % config.SCHEDULER_INTERVAL:
410+
if self.interval_seconds() <= config.SCHEDULER_INTERVAL:
410411
raise ValidationError(
411412
_("Job interval is not a multiple of rq_scheduler's interval frequency: %(interval)ss"),
412413
code="invalid",
@@ -434,13 +435,19 @@ def clean_cron_string(self):
434435
raise ValidationError({"cron_string": ValidationError(_(str(e)), code="invalid")})
435436

436437
def clean(self):
438+
if self.task_type not in TaskType.values:
439+
raise ValidationError(
440+
{"task_type": ValidationError(_("Invalid task type"), code="invalid")},
441+
)
437442
self.clean_queue()
438443
self.clean_callable()
439444
if self.task_type == TaskType.CRON:
440445
self.clean_cron_string()
441446
if self.task_type == TaskType.REPEATABLE:
442447
self.clean_interval_unit()
443448
self.clean_result_ttl()
449+
if self.task_type == TaskType.REPEATABLE and self.scheduled_time is None:
450+
self.scheduled_time = timezone.now() + timedelta(seconds=2)
444451
if self.task_type == TaskType.ONCE and self.scheduled_time is None:
445452
raise ValidationError({"scheduled_time": ValidationError(_("Scheduled time is required"), code="invalid")})
446453
if self.task_type == TaskType.ONCE and self.scheduled_time < timezone.now():

scheduler/tests/test_task_types/test_repeatable_task.py

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,38 @@ class TestRepeatableTask(BaseTestCases.TestSchedulableTask):
1818

1919
def test_create_task_error(self):
2020
scheduled_time = timezone.now()
21-
22-
Task.objects.create(
21+
task = Task.objects.create(
2322
name="konichiva_every_2s",
24-
callable="chat.task_scheduler.konichiva_func",
25-
task_type="REPEATABLE",
26-
interval=2,
23+
callable="scheduler.tests.jobs.test_args_kwargs",
24+
task_type=TaskType.REPEATABLE,
25+
interval=333,
2726
interval_unit="seconds",
2827
queue="default",
2928
enabled=True,
3029
scheduled_time=scheduled_time,
3130
)
31+
self.assertEqual(task.name, "konichiva_every_2s")
32+
self.assertEqual(task.callable, "scheduler.tests.jobs.test_args_kwargs")
33+
self.assertEqual(task.task_type, TaskType.REPEATABLE)
34+
self.assertEqual(task.interval, 333)
35+
self.assertEqual(task.interval_unit, "seconds")
36+
37+
def test_create_task_without_scheduled_time(self):
38+
task = Task.objects.create(
39+
name="konichiva_every_2s",
40+
callable="scheduler.tests.jobs.test_args_kwargs",
41+
task_type=TaskType.REPEATABLE,
42+
interval=33,
43+
interval_unit="seconds",
44+
queue="default",
45+
enabled=True,
46+
)
47+
self.assertAlmostEqual(task.scheduled_time.timestamp(), timezone.now().timestamp(), delta=2)
48+
self.assertEqual(task.name, "konichiva_every_2s")
49+
self.assertEqual(task.callable, "scheduler.tests.jobs.test_args_kwargs")
50+
self.assertEqual(task.task_type, TaskType.REPEATABLE)
51+
self.assertEqual(task.interval, 33)
52+
self.assertEqual(task.interval_unit, "seconds")
3253

3354
def test_unschedulable_old_job(self):
3455
job = task_factory(self.task_type, scheduled_time=timezone.now() - timedelta(hours=1), repeat=0)
@@ -67,16 +88,6 @@ def test_clean_too_frequent(self):
6788
with self.assertRaises(ValidationError):
6889
job.clean_interval_unit()
6990

70-
@override_settings(SCHEDULER_CONFIG=SchedulerConfiguration(SCHEDULER_INTERVAL=10))
71-
def test_clean_not_multiple(self):
72-
job = task_factory(self.task_type)
73-
job.queue = self.queue_name
74-
job.callable = "scheduler.tests.jobs.test_job"
75-
job.interval = 121
76-
job.interval_unit = "seconds"
77-
with self.assertRaises(ValidationError):
78-
job.clean_interval_unit()
79-
8091
def test_clean_short_result_ttl(self):
8192
task = task_factory(self.task_type)
8293
task.queue = self.queue_name

0 commit comments

Comments
 (0)