在Django-Celery中停止/清除定期任务

时间:2011-11-22 17:14:32

标签: django rabbitmq celery django-celery

我设法通过继承PeriodicTask来定期在django-celery中工作。我试图创建一个测试任务并将其设置为运行无用的东西。有用。

现在我无法阻止它。我已经阅读了文档,但我无法找到如何从执行队列中删除任务。我尝试过使用celeryctl并使用shell,但是registry.tasks()是空的,所以我看不出如何删除它。

我已经看到了我应该“撤销”它的建议,但为此我似乎需要一个任务ID,我看不出我将如何找到任务ID。

感谢。

2 个答案:

答案 0 :(得分:21)

任务是一条消息,“周期性任务”会定期发送任务消息。发送的每个任务都将分配一个唯一的ID。

revoke只会取消单个任务讯息。获取必须保留的任务的ID 跟踪发送的ID,但您也可以在发送任务时指定自定义ID。

我不确定您是要取消单个任务消息,还是想要停止定期任务发送更多消息,因此我将列出两者的答案。

没有内置的方法来保持通过定期任务发送的任务的ID, 但是你可以将每个任务的id设置为周期性任务的名称 id将引用随周期性任务发送的任何任务(通常是最后一个)。 您可以通过这种方式指定自定义ID,

使用@periodic_task装饰器:

@periodic_task(options={"task_id": "my_periodic_task"})
def my_periodic_task():
    pass

或使用CELERYBEAT_SCHEDULE设置:

CELERYBEAT_SCHEDULE = {name: {"task": task_name,
                              "options": {"task_id": name}}}

如果您要删除定期任务,只需从代码库中删除@periodic_task,或从CELERYBEAT_SCHEDULE中删除该条目即可。 如果您使用的是Django数据库调度程序,则必须删除定期任务 来自Django Admin界面。

PS1:revoke不会停止已经启动的任务。它只取消了 还没有开始的任务。您可以使用终止正在运行的任务 revoke(task_id, terminate=True)。默认情况下,这将发送TERM信号 这个过程,如果你想发送另一个信号(例如KILL)使用 revoke(task_id, terminate=True, signal="KILL")

PS2:revoke是一个远程控制命令,因此只有RabbitMQ支持它 和Redis经纪人运输。 如果您希望任务支持取消,您应该通过存储cancelled来完成此操作 在数据库中标记并让任务在启动时检查该标志:

from celery.task import Task

class RevokeableTask(Task):
    """Task that can be revoked.

    Example usage:

        @task(base=RevokeableTask)
        def mytask():
            pass
    """

    def __call__(self, *args, **kwargs):
        if revoke_flag_set_in_db_for(self.request.id):
            return
        super(RevokeableTask, self).__call__(*args, **kwargs)

答案 1 :(得分:3)

以防万一这可能对某人有所帮助......我们在工作中遇到了同样的问题,并且妄图找到某种管理命令去除周期性任务,我们做不到。所以这里有一些指示。

您可能应首先仔细检查您正在使用的scheduler class

  

默认调度程序是celery.beat.PersistentScheduler,它只是跟踪本地数据库文件(搁置)中的最后运行时间。

在我们的案例中,我们使用的是djcelery.schedulers.DatabaseScheduler类。

  

django-celery 还附带了一个调度程序,用于将计划存储在Django数据库中

虽然文档确实提到了一种删除周期性任务的方法:

  

使用 django-celery 的调度程序,您可以从Django Admin添加,修改和删除定期任务。

我们希望以编程方式执行删除,或者通过shell中的(celery / management)命令执行删除。

由于我们找不到命令行,我们使用了django / python shell:

$ python manage.py shell
>>> from djcelery.models import PeriodicTask
>>> pt = PeriodicTask.objects.get(name='the_task_name')
>>> pt.delete()

我希望这有帮助!