我整天都在和这项任务作斗争。
我有一个Django应用程序。我使用Celery进行异步任务。偶尔,我想创建一个定期任务。任务运行未知的次数,但需要稍后删除。所以任务可能是这样的:
@shared_task
def foobar_task(id):
if this_should_run:
do_task()
else:
PeriodicTask.objects.get(name='{} task'.format(id)).delete()
我的应用正在运行。我有芹菜在Docker容器中运行,使用celery --app=myproject beat --loglevel=info --scheduler=django
运行。我有另一个运行标准芹菜工人的容器。
所以现在我想动态创建我的周期性任务。我有一个视图/ API端点,触发这样的事情:
schedule, _ = IntervalSchedule.objects.get_or_create(every=15, period=IntervalSchedule.SECONDS)
PeriodicTask.objects.create(interval=schedule,
name='{} task'.format(id),
task='myapp.tasks.foobar_task')
在Django管理员中,我可以看到已创建周期性任务。然而,观察芹菜容器和芹菜捣蛋容器的日志,没有任何反应。
为什么芹菜没有意识到那是一项新的定期任务?每次创建或删除新任务时,我都不想重启celery beat。
注意:我使用的是Django 1.11.2,PostgreSQL,Celery 4.0.2,Django Celery Beat 1.0.1。
答案 0 :(得分:1)
您可以创建一个类似下面的自定义调度程序,改编自this answer。
from django_celery_beat.schedulers import DatabaseScheduler
class AutoUpdateScheduler(DatabaseScheduler):
def tick(self, *args, **kwargs):
if self.schedule_changed():
self.sync()
self._heap = None
new_schedule = self.all_as_schedule()
if new_schedule:
to_add = [x for x in new_schedule.keys() if x not in self.schedule.keys()]
to_remove = [x for x in self.schedule.keys() if x not in new_schedule.keys()]
for key in to_add:
self.schedule[key] = new_schedule[key]
for key in to_remove:
del self.schedule[key]
super(AutoUpdateScheduler, self).tick(*args, **kwargs)
@property
def schedule(self):
if not self._initial_read and not self._schedule:
self._initial_read = True
self._schedule = self.all_as_schedule()
return self._schedule
当你经营芹菜时,请将它指向这个班级:
celery --app=myproject beat --loglevel=info --scheduler=myproject.scheduler.AutoUpdateScheduler