我的应用程序蜘蛛各种网站,并使用Celery以一种漂亮的分布式方式进行。
蜘蛛可以分成几个阶段,有点像链条,除了我不确切地知道每个阶段将会提前完成哪些任务。例如,许多蜘蛛运行一个任务来获取结果列表,然后为每个结果运行另一个任务以获得有关结果的更多信息。我打算将这种新事物称为"未知的链条"。
我的问题是如何实现未知链。我希望能够在任何可以使用链的地方使用它,例如同步等待它,运行它回调,或(最重要的是)将它放入和弦。
我目前的解决方案是让每个阶段的任务返回下一阶段的签名。然后我可以创建一个同步等待未知链完成的函数:
def run_unknown_chain_sync(unknown_chain):
result = unknown_chain.delay().get()
while isinstance(result, Signature):
result = result.delay().get()
return result
另一个与回调异步执行的函数+任务:
def run_query_async(unknown_chain):
unknown_chain_advance.delay(unknown_chain, callback)
@app.task
def unknown_chain_advance(unknown_chain, callback):
if isinstance(unknown_chain, Signature):
chain(unknown_chain, unknown_chain_advance(callback)).delay()
else:
callback.delay(result)
此解决方案的主要问题是未知链不能用于和弦。
我提出的其他想法:
在Celery的内部做一些令人讨厌的事情并以某种方式创造出一种代表未知链条的新任务。如果它看起来像一个任务,它应该像任务一样工作。
它将拦截报告任务完成的任何内容,并检查任务是否实际完成或只是返回下一阶段。如果它回到下一阶段,它会忘记"将任务报告为已完成并开始下一阶段,并将某些内容链接到重复该过程的内容。
不是一个好主意,因为当我更新Celery时它会破坏。此外,我对Celery代码库的看法并不太近,但我怀疑这可能是不可能的。
创建一种新的原语,类似chain
,但称为unknown_chain
。我怀疑这可以做到,因为从我对芹菜代码的阅读中,Celery并不是为了让你能够制作出像这样的新签名。
创建我自己的未知链的方法,就像我发明了一种用回调来运行它们的方式。问题是,你到底该怎么做?