如何在多个芹菜进程中跟踪已撤销的任务

时间:2012-04-08 13:01:54

标签: python celery celeryd

我有一个提醒类型的应用程序,使用“eta”参数计划芹菜中的任务。如果提醒对象中的参数发生变化(例如提醒时间),则我撤销先前发送的任务并排队新任务。

我想知道是否有任何好方法可以跟踪芹菜重启的撤销任务。我希望能够动态地上下调整celeryd进程,似乎在发送revoke命令后启动的任何celeryd进程仍将执行该任务。

执行此操作的一种方法是保留已撤销的任务ID列表,但此方法将导致列表任意增长。修剪此列表需要保证任务不再在RabbitMQ队列中,这似乎是不可能的。

我也尝试为每个celeryd工作者使用一个共享的--statedb文件,但似乎只有在工作人员终止时才更新statedb文件,因此不适合我想要完成的工作。< / p>

提前致谢!

3 个答案:

答案 0 :(得分:1)

有趣的问题,我认为使用广播命令应该很容易解决。 如果新工作人员启动时,它会请求所有其他工作人员转储其已撤销的工作人员 对新工人的任务。添加两个新的远程控制命令, 您可以使用@Panel.register

轻松添加新命令

模块control.py:

from celery.worker import state
from celery.worker.control import Panel

@Panel.register
def bulk_revoke(panel, ids):
    state.revoked.update(ids)

@Panel.register
def broadcast_revokes(panel, destination):
    panel.app.control.broadcast("bulk_revoke", arguments={
         "ids": list(state.revoked)},
         destination=destination)

将其添加到CELERY_IMPORTS:

CELERY_IMPORTS = ("control", )

现在唯一缺少的问题是连接它以便新工作人员 在启动时触发broadcast_revokes。我想你可以使用worker_ready 信号:

from celery import current_app as celery
from celery.signals import worker_ready

def request_revokes_at_startup(sender=None, **kwargs):
    celery.control.broadcast("broadcast_revokes",
                             destination=sender.hostname)

答案 1 :(得分:0)

我必须在我的项目中执行类似操作,并将celerycamdjango-admin-monitor一起使用。监视器获取任务快照并定期将其保存在数据库中。并且有一个很好的用户界面来浏览和检查所有任务的状态。你甚至可以使用even if your project is not Django based

答案 2 :(得分:0)

我前段时间实现了类似的功能,我提出的解决方案与你的解决方案非常相似。

我解决这个问题的方法是让工作人员在作业运行时从数据库中获取Task对象(通过传递主键,如文档所推荐的那样)。在您的情况下,在发送提醒之前,工作人员应执行检查以确保任务“准备好”运行。如果没有,它应该简单地返回而不做任何工作(假设ETA已经改变而另一个工人将拿起新工作)。