删除已撤销的Celery任务

时间:2017-09-03 01:30:12

标签: python-3.x celery

根据task.revoke()上的docs

  

所有工作节点都保留已撤销任务ID的内存,无论是在内存中还是在磁盘上持久

  

通过向所有工作人员发送广播消息来撤销任务,工作人员会在内存中保留已撤销任务的列表。当工作人员启动时,它会将已撤销的任务与群集中的其他工作人员同步。

听起来这些任务在您撤销之后仍然存在。我不明白为什么没有明确的方法来撤销任务并将其从队列中删除。

文档似乎意味着您需要无限期地保留已撤销任务的列表,以确保新工作人员在某些情况下不会接收它们。

我也知道有一个完全清除任务队列的功能,但这不是我想要的。

有没有办法撤销任务并从Celery的任务队列中清除它(只有它)?

2 个答案:

答案 0 :(得分:0)

除了用purge或用broker中的手动命令删除所有消息外,不可能仅删除队列中的一封邮件

但是,您可能不介意由工作人员处理的撤消任务从队列中删除。因此,您不必维护一个永久吊销的ID列表。

仅当工作人员忙于该任务或计划将任务安排在以后时,才应将ID保留在该工作人员尚未处理的列表上。

如果可以同时停止所有工作人员并且您要保留已标记的已撤销任务,则该列表应该是持久的。否则,一名新工人会向已经在运行的工人询问要标记为已撤消的任务。

注意:我分析了一个以Redis为经纪人和后端的案例,以获取答案。最终被撤消的任务从队列中删除,因此可见(标记为已撤消)。

示例:

  1. ID为'A'的任务被推入队列并计划在1小时内完成
  2. 任务'A'为revoke(),因此会向所有工作人员发送一条消息,以将任务标记为已撤消。该ID在每个工作人员的撤消列表中(请参阅日志Tasks flagged as revoked: A中的内容)
  3. 任务'A'仍在等待ETA的队列中
  4. 一个小时后,工人执行任务。由于该任务被标记为已撤消,因此工作人员不执行任务,而是立即将任务结果写入后端。结果表明任务已被撤销(因此未执行)。

我不知道您不能直接从队列中删除任务的确切原因。但是我的直觉是:

  • 所有经纪人可能不允许删除队列中间的元素
  • 立即删除任务并使任务系统一致可能更难。而且,由于Celery团队的劳动力有限,因此他们不希望支持更简单的解决方案

答案 1 :(得分:0)

Celery文档中有一小段漂亮的小节,名为“ revoke: Revoking tasks”,请仔细阅读。

简而言之-默认行为是正常停止任务。此外,任务可能只是在队列中等待,在这种情况下,撤消只是将其从队列中删除(最简单的情况)。更为复杂的是当任务已经在运行时...使用terminate=True,您告诉Celery worker将SIGINT发送给执行任务的worker进程。但是在某些情况下可能不起作用。 -就像您在Linux中具有“僵尸进程”一样,您可能具有难以撤销的“僵尸任务”(我知道-这不是最好的类比,但是您会明白这一点),在这种情况下,您可以通过以下方式撤销它们SIGKILL(通过terminate=True, signal='SIGKILL'撤消)。撤消成功后,您将不会在队列中看到该任务。