从任务 id 创建一个AsyncResult 对象是在FAQ 中推荐的方式来获取任务状态,当你唯一拥有的是任务 id 时。
但是,从 Celery 3.x 开始,如果人们不注意它们,有一些重要的警告可能会咬人。这真的取决于具体的用例场景。
默认情况下,Celery 不记录“运行”状态。
为了让 Celery 记录任务正在运行,您必须将 task_track_started 设置为 True。这是一个测试这个的简单任务:
@app.task(bind=True)
def test(self):
print self.AsyncResult(self.request.id).state
当task_track_started 为False(默认)时,即使任务已启动,状态显示为PENDING。如果将task_track_started 设置为True,则状态将为STARTED。
PENDING 状态表示“我不知道”。
状态为PENDING 的AsyncResult 并不意味着Celery 不知道任务的状态。这可能是由于多种原因。
一方面,AsyncResult 可以使用无效的任务 ID 构造。这样的“任务”将被 Celery 视为未决:
>>> task.AsyncResult("invalid").status
'PENDING'
好的,所以没有人会将显然无效的 id 提供给AsyncResult。很公平,但它也有效果,AsyncResult 还将考虑一个已成功运行但 Celery 忘记为 PENDING 的任务。再次,在某些用例中场景 这可能是个问题。部分问题取决于如何配置 Celery 以保留任务结果,因为它取决于结果后端中“墓碑”的可用性。 (“墓碑”是 Celery 文档中用于记录任务如何结束的数据块的术语。)如果 task_ignore_result 是 True,则使用 AsyncResult 根本不起作用。一个更令人烦恼的问题是 Celery 默认会过期墓碑。 result_expires 默认设置为 24 小时。因此,如果您启动一个任务,并将 id 记录在长期存储中,并在 24 小时后,您使用它创建一个AsyncResult,状态将为PENDING。
所有“真正的任务”都以PENDING 状态开始。因此,在一项任务上获得PENDING 可能意味着该任务已被请求但从未比这更进一步(无论出于何种原因)。或者这可能意味着任务运行但 Celery 忘记了它的状态。
哎哟! AsyncResult 对我不起作用。我还能做什么?
我更喜欢跟踪目标,而不是跟踪任务本身。我确实保留了一些任务信息,但它对于跟踪目标确实是次要的。目标存储在独立于 Celery 的存储中。当一个请求需要执行计算取决于某个目标是否已经实现时,它会检查该目标是否已经实现,如果是,则使用此缓存的目标,否则启动将影响该目标的任务,并发送到发出 HTTP 请求的客户端响应指示它应该等待结果。
上面的变量名和超链接是针对 Celery 4.x 的。在 3.x 中对应的变量和超链接为:CELERY_TRACK_STARTED、CELERY_IGNORE_RESULT、CELERY_TASK_RESULT_EXPIRES。