在运行时添加和删除Celery定期任务

时间:2017-07-04 15:50:47

标签: django celery celerybeat

我整天都在和这项任务作斗争。

我有一个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。

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