使用主题交换将消息从一种方法发送到另一种方法

时间:2013-01-04 10:03:00

标签: django message-queue celery django-celery kombu

最近,我一直在寻找celery& kombu文档,因为我需要将它们集成到我的一个项目中。我对这应该如何工作有一个基本的了解,但使用不同经纪人的文档示例让我感到困惑。

以下是该方案:

在我的应用程序中,我有两个视图ViewAViewB这两个视图都做了一些昂贵的处理,所以我想让他们使用芹菜任务进行处理。所以这就是我所做的。

views.py

def ViewA(request):
    tasks.do_task_a.apply_async(args=[a, b])


def ViewB(request):
    tasks.do_task_b.apply_async(args=[a, b])

tasks.py

@task()
def do_task_a(a, b):
    # Do something Expensive

@task()
def do_task_b(a, b):
    # Do something Expensive here too

直到现在,一切正常。问题是do_task_a在系统上创建了一个txt文件,我需要在do_task_b中使用该文件。现在,在do_task_b方法中,我可以检查文件是否存在并调用任务retry方法[这就是我现在正在做的]如果文件不存在。

在这里,我宁愿采取不同的方法(即消息传入的地方)。我希望do_task_a在创建文件后向do_task_b发送消息,而不是循环重试方法,直到创建文件。

我仔细阅读了celerykombu的文档,并按如下方式更新了我的设置。

BROKER_URL = "django://"
CELERY_RESULT_BACKEND = "database"
CELERY_RESULT_DBURI = "sqlite:///celery"
TASK_RETRY_DELAY = 30 #Define Time in Seconds
DATABASE_ROUTERS = ['portal.db_routers.CeleryRouter']
CELERY_QUEUES = ( 
    Queue('filecreation', exchange=exchanges.genex, routing_key='file.create'),
)
CELERY_ROUTES = ('celeryconf.routers.CeleryTaskRouter',)

我被困在这里。 不知道从哪里开始。

我应该怎样做才能使do_task_a在创建文件时向do_task_b广播消息?如何使do_task_b接收(消费)消息并进一步处理代码?

欢迎任何想法和建议。

1 个答案:

答案 0 :(得分:1)

这是使用 Celery的回调/链接功能的一个很好的例子。

Celery支持将任务链接在一起,以便一个任务跟随另一个任务。 您可以阅读更多相关信息here

apply_async()函数有两个可选参数

+link : excute the linked function on success 
+link_error : excute the linked function on an error

@task
def add(a, b):
    return a + b

@task
def total(numbers):
    return sum(numbers)

@task
def error_handler(uuid):
    result = AsyncResult(uuid)
    exc = result.get(propagate=False)
    print('Task %r raised exception: %r\n%r' % (exc, result.traceback))

现在在您的调用函数中执行类似

的操作
def main():
    #for error_handling
    add.apply_async((2, 2), link_error=error_handler.subtask())

    #for linking 2 tasks
    add.apply_async((2, 2), link=add.subtask((8, )))
    # output 12

    #what you can do is your case is something like this. 
    if user_requires:
        add.apply_async((2, 2), link=add.subtask((8, )))
    else:
        add.apply_async((2, 2))

希望这是有帮助的