了解芹菜任务是否存在

dom*_*nik 41 python status task celery

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

>>> AsyncResult('...').status
'PENDING'
Run Code Online (Sandbox Code Playgroud)

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

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

ask*_*sol 31

在发送任务时,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

# when using celery versions older than 4.0, use body instead of headers

@after_task_publish.connect
def update_sent_state(sender=None, headers=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(headers['id'], None, "SENT")
Run Code Online (Sandbox Code Playgroud)

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

>>> result.state != "PENDING"
Run Code Online (Sandbox Code Playgroud)

  • 值得一提的是,清除队列并不会删除任务元(至少在使用Redis作为后端时).因此,无法可靠地使用此方法来确定任务是否仍然存在. (3认同)
  • 同时使用 [`task_track_started`](http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-track-started) 时可能会出现竞争条件。从我的测试来看,如果任务队列为空,则它会在执行此回调之前立即启动任务(并且其状态设置为“已启动”),至少在“store_result”实际将状态设置为“已发送”之前。然后状态设置为“已发送”并且“已开始”信息丢失。 (3认同)
  • @Jérôme,你是救星,我们复制粘贴了这个,但不明白为什么我们的一些任务永远停留在“已发送”状态。实际上,他们会先收到“成功”的更新,然后收到“已发送”的更新。 (2认同)

mhe*_*her 9

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

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"
... 
Run Code Online (Sandbox Code Playgroud)

  • 问题是我只有一个id.每个id都曾经是一个有效的id,但有些不再是因为结果从后端删除了.所以我总是会有一个以`celery-task-id -`开头的id,但任务可能仍然无效. (3认同)
  • 在这种情况下,您应该在外部跟踪id历史.芹菜后端不保证永远保持所有结果.例如,amqp后端只能查询一次. (2认同)