问题
我已经将一个长时间运行的任务分割成逻辑子任务,所以我可以在每个子任务完成时报告它的结果。但是,我正在尝试报告一项实际上永远不会完成的任务的结果(而是在执行过程中产生价值),并且正在努力使用我现有的解决方案来做到这一点。
背景
我正在为我编写的一些 Python 程序构建一个 Web 界面。用户可以通过 Web 表单提交作业,然后返回查看作业的进度。
假设我有两个函数,每个函数都通过单独的表单访问:
med_func
: 执行大约需要 1 分钟,结果被传递给render()
,这会产生额外的数据。long_func
: 返回一个生成器。每个yield
需要 30 分钟,并且应该报告给用户。有这么多的产量,我们可以认为这个迭代器是无限的(仅在撤销时终止)。
代码,当前实现
使用med_func
,我报告结果如下:
在提交表单时,我将一个保存AsyncResult
到Django 会话:
task_result = med_func.apply_async([form], link=render.s())
request.session["task_result"] = task_result
结果页面的 Django 视图访问 this AsyncResult
。任务完成后,结果将保存到一个对象中,该对象作为上下文传递给 Django 模板。
def results(request):
""" Serve (possibly incomplete) results of a session's latest run. """
session = request.session
try: # Load most recent task
task_result = session["task_result"]
except KeyError: # Already cleared, or doesn't exist
if "results" not in session:
session["status"] = "No job submitted"
else: # Extract data from Asynchronous Tasks
session["status"] = task_result.status
if task_result.ready():
session["results"] = task_result.get()
render_task = task_result.children[0]
# Decorate with rendering results
session["render_status"] = render_task.status
if render_task.ready():
session["results"].render_output = render_task.get()
del(request.session["task_result"]) # Don't need any more
return render_to_response('results.html', request.session)
此解决方案仅在函数实际终止时才有效。我无法将 的逻辑子任务链接在一起long_func
,因为yield
s 的数量未知(循环的每次迭代long_func
可能不会产生结果)。
问题
是否有任何明智的方法可以从极其长时间运行的 Celery 任务中访问产生的对象,以便在生成器耗尽之前显示它们?