了解芹菜任务是否存在

时间:2012-03-22 14:21:05

标签: python task status celery

是否可以找出具有特定任务ID的任务是否存在?当我试图获得状态时,我将永远等待。

>>> AsyncResult('...').status
'PENDING'

我想知道给定的任务ID是否是真正的芹菜任务ID而不是随机字符串。我想要不同的结果,具体取决于是否有某个id的有效任务。

过去可能存在具有相同ID的有效任务,但结果可能已从后端删除。

6 个答案:

答案 0 :(得分:28)

Celery在发送任务时没有写入状态,这部分是优化 (见http://docs.celeryproject.org/en/latest/userguide/tasks.html#state)。

如果你真的需要它,可以很简单地添加:

from celery import current_app
# `after_task_publish` is available in celery 3.1+
# for older versions use the deprecated `task_sent` signal
from celery.signals import after_task_publish

@after_task_publish.connect
def update_sent_state(sender=None, body=None, **kwargs):
    # the task may not exist if sent using `send_task` which
    # sends tasks by name, so fall back to the default result backend
    # if that is the case.
    task = current_app.tasks.get(sender)
    backend = task.backend if task else current_app.backend

    backend.store_result(body['id'], None, "SENT")

然后你可以测试PENDING状态来检测任务没有(貌似) 已发送:

>>> result.state != "PENDING"

答案 1 :(得分:9)

AsyncResult.state在未知任务ID的情况下返回PENDING。

  

待定

     

任务正在等待执行或未知。任何不是的任务ID   已知隐含处于待定状态。

http://docs.celeryproject.org/en/latest/userguide/tasks.html#pending

如果您需要区分未知ID和现有ID,则可以提供自定义任务ID:

>>> from tasks import add
>>> from celery.utils import uuid
>>> r = add.apply_async(args=[1, 2], task_id="celery-task-id-"+uuid())
>>> id = r.task_id
>>> id
'celery-task-id-b774c3f9-5280-4ebe-a770-14a6977090cd'
>>> if not "blubb".startswith("celery-task-id-"): print "Unknown task id"
... 
Unknown task id
>>> if not id.startswith("celery-task-id-"): print "Unknown task id"
... 

答案 2 :(得分:2)

现在我正在使用以下方案:

  1. 获取任务ID。
  2. 设置为memcache密钥,例如'task_%s'%task.id消息'已启动'。
  3. 将任务ID传递给客户端。
  4. 现在从客户端我可以监控任务状态(从任务消息设置到内存缓存)。
  5. 从准备就绪 - 设置到memcache密钥消息'Ready'。
  6. 从任务就绪的客户端开始 - 启动特殊任务,从memcache中删除密钥并执行必要的清理操作。

答案 3 :(得分:0)

您需要在您创建的AsyncTask对象上调用.get()以实际从后端获取结果。

请参阅Celery FAQ


进一步澄清我的答案。

任何字符串在技术上都是有效的ID,无法验证任务ID。找出任务是否存在的唯一方法是询问后端是否知道该任务,并且必须使用.get()

这引入了.get()阻止后端没有任何关于您提供的任务ID的信息的问题,这是设计允许您启动任务然后等待其完成。

在原始问题的情况下,我将假设OP想要获得先前完成的任务的状态。为此,您可以传递一个非常小的超时并捕获超时错误:

from celery.exceptions import TimeoutError
try:
    # fetch the result from the backend
    # your backend must be fast enough to return
    # results within 100ms (0.1 seconds)
    result = AsyncResult('blubb').get(timeout=0.1)
except TimeoutError:
    result = None

if result:
    print "Result exists; state=%s" % (result.state,)
else:
    print "Result does not exist"

不言而喻,只有当你的后端存储结果时,这才有效,如果没有办法知道某个任务ID是否有效,因为没有任何东西记录它们。


更加澄清。

使用AMQP后端无法完成您想要做的事情,因为it does not store results, it forwards them

我的建议是切换到数据库后端,以便结果在数据库中,您可以在现有的celery模块之外查询。如果结果数据库中不存在任何任务,则可以认为该ID无效。

答案 4 :(得分:-3)

尝试

AsyncResult('blubb').state

可能有效。

它应该返回不同的东西。

答案 5 :(得分:-3)

如果我错了,请纠正我。

if built_in_status_check(task_id) == 'pending'
   if registry_exists(task_id) == true
      print 'Pending'
   else
      print 'Task does not exist'