Celery画布行为在异步和渴望模式之间有所不同

时间:2019-07-11 17:31:40

标签: celery celery-task celery-canvas

Celery画布在异步和渴望模式下的工作方式存在一些差异。我注意到,在动态任务中替换自身的一组后跟一个链条不会将结果发送到链条中的下一个。

好吧,这看起来很复杂,让我举个例子:

给出以下任务:

@shared_task(bind=True)
def grouped(self, val):
    task = (
        group(asum.s(val, n) for n in range(val)) | asum.s(val)
    )
    raise self.replace(task)

当它被分组在另一个这样的画布中时:

@shared_task(bind=True)
def flow(self, val):
    workflow = (asum.s(1, val) |
                asum.s(2) |
                grouped.s() |
                amul.s(3))

    return self.replace(workflow)

任务 amul 在急切模式下不会收到分组的结果。

为了真正说明问题,我在github上创建了一个示例项目,您可以深入研究问题并通过一些快速解决方案以及芹菜项目的一些公关帮助我。

https://github.com/gutomaia/celery_equation

----已编辑----

在项目中,我陈述了使用芹菜的两种方式的不同行为。在异步模式下,thouse任务可以按预期工作。

>>> from equation.main import *
>>> from equation.tasks import *
>>> flow.delay(1).get()
78
>>> flow.delay(2).get()
120
>>> flow.delay(100).get()
47895

3 个答案:

答案 0 :(得分:1)

可悲的是,急切模式永远不会与运行实际工作程序相同。在运行实际工作人员进行急切模式时有太多复杂性,难道是一回事。 我同意在使用急切模式时应将此类情况归入特殊情况,但预计会有一些差异。 如果您知道如何解决此问题,请提交PR,我们可以在那里查看修复。谢谢!

答案 1 :(得分:1)

在一个测试案例中,我正在为这种情况而苦苦挣扎。对于将来的读者,至少从celery 4.4.0版本开始,以下惯用语将在所有情况下都适用,包括同步的进程内执行:

    return self.replace(...)

使用raise或仅让函数在Task.replace之后立即结束只能在异步模式下工作。相关代码为right at the end of Task.replace

        if self.request.is_eager:
            return sig.apply().get()
        else:
            sig.delay()
            raise Ignore('Replaced by new task')

答案 2 :(得分:0)

grouped()不返回任何内容,那么您如何期望 amul 得到结果?