【发布时间】:2014-07-10 17:30:41
【问题描述】:
我的问题可能很基本,但我仍然无法在官方文档中找到解决方案。我在我的 Django 应用程序中定义了一个 Celery 链,执行一组依赖于其他的任务:
chain( tasks.apply_fetching_decision.s(x, y),
tasks.retrieve_public_info.s(z, x, y),
tasks.public_adapter.s())()
显然第二个和第三个任务需要父级的输出,这就是我使用链的原因。
现在的问题是:如果第一个任务中的测试条件失败,我需要以编程方式撤销第二个和第三个任务。如何以干净的方式做到这一点?我知道我可以从定义链的方法中撤销链的任务(请参阅thisquestion 和 this doc),但 内部 第一个任务我看不到后续任务也不是链条本身。
临时解决方案
我目前的解决方案是跳过根据前一个任务的结果在后续任务中的计算:
@shared_task
def retrieve_public_info(result, x, y):
if not result:
return []
...
@shared_task
def public_adapter(result, z, x, y):
for r in result:
...
但是这种“解决方法”有一些缺陷:
- 为每个任务添加不必要的逻辑(基于前任的结果),从而影响重用
- 仍然执行后续任务,以及所有由此产生的开销
我没有过多地将链的引用传递给任务,因为我担心会搞砸事情。我也承认我还没有尝试过抛出异常的方法,因为我认为不通过链继续进行的选择可能是一种功能性(因此非异常)场景......
感谢您的帮助!
【问题讨论】:
-
您可以传递结果的元组和成功消息,而不是只传递结果的值。用更高的术语来说,这可以实现为 Error Monad 或 Maybe Monad:haskell.org/haskellwiki/All_About_Monads#The_Error_monaden.wikipedia.org/wiki/…
-
这并不妨碍后续N个链任务的执行。我要避免的正是徒劳地调用和执行任务的开销。