从嵌套的链和和弦中获取所有任务ID

时间:2014-04-10 14:17:06

标签: python redis celery

我正在使用带有Redis后端的Celery 3.1.9。我正在运行的工作由几个以和弦和链条运行的子任务组成。结构如下所示:

  1. 制备
  2. 下载数据(2名工人的和弦)
  3. 解析并存储下载的数据
  4. 4名工人的长期和弦
  5. 最终化
  6. 生成报告
  7. 列表中的每个项目都是一个子任务,它们都链接在一起。第2步和第4步是和弦。整个过程通过为第4步创建一个和弦来连接,其回调是4 - >的链。然后,如图6所示,为步骤2创建和弦,谁的回叫是3 - >第一个和弦。然后,最后创建一个链1 - >第二个和弦。然后使用delay()启动该链,并将其ID存储在数据库中。

    问题是双重的,首先我希望能够撤销整个事情,其次我希望在我的Task类上有一个自定义的on_failure进行一些清理,然后向用户报告失败。

    目前我存储了链的任务ID,我想我可以用它来撤销链。此外,如果出现错误,我想将链路连接到它的根(在on_failure处理程序中)以从数据库中检索相关记录。这不起作用,因为当您仅使用任务的ID重新创建AsyncResult实例时,它的父属性为None。

    我尝试的第二件事是存储在外链的结果上调用的serializable()的结果。但是,这不会返回整个AsyncResult对象树,它只返回链中第一级的ID(因此不是和弦中子项的ID。)

    我尝试的第三件事就是基本上自己实现serializable(),但事实证明,原始方法之所以没有超过2级是因为链的子节点是celery.canvas.chord对象,而不是AsyncResult实例。

    问题的说明:

    chord([
        foo.si(),
        foo.si(),
        foo.si(),
    ], bar.si() | bar.si())
    res = chord.apply_async()
    pprint(res.serializable())
    

    打印以下内容:

    (('50c9eb94-7a63-49dc-b491-6fce5fed3713',
      ('d95a82b7-c107-4a2c-81eb-296dc3fb88c3',
       [(('7c72310b-afc7-4010-9de4-e64cd9d30281', None), None),
        (('2cb80041-ff29-45fe-b40c-2781b17e59dd', None), None),
        (('e85ab83d-dd44-44b5-b79a-2bbf83c4332f', None), None)])),
     None)
    

    第一个ID是回调链的id,第二个ID来自和弦任务本身,后三个是和弦内的实际任务。但我无法从回调链中的任务(即两个bar.si()调用的ID)得到结果。

    有没有办法获得实际的任务ID?

1 个答案:

答案 0 :(得分:0)

一种骇人听闻的方法是使用apply_async调用任务,保存任务ID,然后手动等待它们。这样,您将完全控制事件的发生,但您只能等待异步任务作为最后的选择。现在,您可以访问任务ID,返回值等。例如:

 task1 = a_task.apply_async()
 task2 = b_task.apply_async()
 task3 = c_task.apply_async()

 tasks = [task1, task2, task3]

 for task in tasks:
     task.wait()