在芹菜中如何获得队列中的任务位置?

时间:2012-06-04 23:00:11

标签: python redis celery django-celery djcelery

我正在使用Celery和Redis作为代理,我可以看到队列实际上是一个redis列表,其中序列化任务作为项目。

我的问题是,如果我在调用<task>.delay()时有一个AsyncResult对象,有没有办法确定项目在队列中的位置?

更新

我终于可以使用以下方式获得该职位:

from celery.task.control import inspect
i = inspect()
i.reserved()

但它有点慢,因为它需要与所有工人沟通。

1 个答案:

答案 0 :(得分:9)

你提到的inspect.reserved()/scheduled()可能有用,但不行 始终准确,因为它只考虑任务 工人们预先准备好了。

Celery不允许队列上的带外操作,例如删除消息 从队列中,或重新排序它们,因为它不会在分布式系统中扩展。 消息可能尚未到达队列,这可能导致 在竞争条件下并且在实践中它不是具有事务性的顺序队列 操作,但源自多个位置的消息流。 也就是说,Celery API基于严格的消息传递语义。

可以直接在某些代理上访问队列 Celery支持(如Redis或Database),但这不是公共API的一部分, 你不鼓励这样做,但当然如果你没有计划 大规模支持操作,您应该做最方便的事情 并放弃我的建议。

如果这只是为了让用户知道他的工作何时完成,那么 我相信你可以想出一个算法来预测任务何时执行, 如果您只有队列的长度和插入每个任务的时间。

第一个是redis.len("celery"),后者可以 通过聆听task_sent信号来添加自己:

from celery.signals import task_sent

@task_sent.connect
def record_insertion_time(id, **kwargs):
   redis.zadd("celery.insertion_times", id)

在此处使用排序集:http://redis.io/commands/zadd

对于纯消息传递解决方案,您可以使用专用监视器 消耗Celery事件流并预测任务何时完成。 http://docs.celeryproject.org/en/latest/userguide/monitoring.html#event-reference

(只是注意到任务发送中缺少时间戳字段 文档,但随着该事件发送时间戳,所以我将修复它。)

事件还包含一个“时钟”字段,它是一个逻辑时钟 (见http://en.wikipedia.org/wiki/Lamport_timestamps), 这可以用于检测分布式事件的顺序 系统不依赖于每台机器上的系统时间 同步(这是不可能实现的)。