芹菜相当于JoinableQueue

时间:2016-09-08 22:58:41

标签: python queue celery python-multiprocessing gevent

Celery相当于multiprocessing.JoinableQueue(或gevent.queue.JoinableQueue)会是什么?

我正在寻找的功能是能够.join()来自发布者的Celery任务队列,等待队列中的所有任务完成。

等待初始AsyncResultGroupResult不足够,因为队列会自动填满工作人员。

1 个答案:

答案 0 :(得分:0)

这可能不完美,但这是我最终提出来的。

它基本上是现有Celery队列之上的JoinableQueue包装器,基于共享的Redis计数器和列表侦听器。它要求队列名称与其路由密钥相同(由于before_task_publishtask_postrun信号的内部实现细节。)

<强> joinableceleryqueue.py

from celery.signals import before_task_publish, task_postrun
from redis import Redis
import settings

memdb = Redis.from_url(settings.REDIS_URL)

class JoinableCeleryQueue(object):
    def __init__(self, queue):
        self.queue = queue
        self.register_queue_hooks()

    def begin(self):
        memdb.set(self.count_prop, 0)

    @property
    def count_prop(self):
        return "jqueue:%s:count" % self.queue

    @property
    def finished_prop(self):
        return "jqueue:%s:finished" % self.queue

    def task_add(self, routing_key, **kw):
        if routing_key != self.queue:
            return

        memdb.incr(self.count_prop)

    def task_done(self, task, **kw):
        if task.queue != self.queue:
            return

        memdb.decr(self.count_prop)
        if memdb.get(self.count_prop) == "0":
            memdb.rpush(self.finished_prop, 1)

    def register_queue_hooks(self):
        before_task_publish.connect(self.task_add)
        task_postrun.connect(self.task_done)

    def join(self):
        memdb.brpop(self.finished_prop)

我选择使用BRPOP而不是pub / sub,因为我只需要一个监听器来监听“所有任务完成”事件(发布者)。

使用JoinableCeleryQueue非常简单 - begin()在将任何任务添加到队列之前,使用常规Celery API .join()添加任务以等待所有任务完成。< / p>