特定のタスクIDのタスクが存在するかどうかを確認することはできますか?ステータスを取得しようとすると、常に保留になります。
>>> AsyncResult('...').status
'PENDING'
特定のタスクIDが実際のセロリタスクIDであり、ランダムな文字列ではないかどうかを知りたいです。特定のIDに対して有効なタスクがあるかどうかに応じて、異なる結果が必要です。
同じidの有効なタスクが過去にあった可能性がありますが、結果はバックエンドから削除された可能性があります。
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")
次に、PENDING状態をテストして、タスクが(一見)送信されていないことを検出できます。
>>> result.state != "PENDING"
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"
...
現在、私は次のスキームを使用しています:
バックエンドから結果を実際にフェッチするには、作成したAsyncTaskオブジェクトで.get()
を呼び出す必要があります。
Celery FAQ を参照してください。
私の答えをさらに明確にするため。
文字列は技術的には有効なIDであり、タスクIDを検証する方法はありません。タスクが存在するかどうかを確認する唯一の方法は、バックエンドがそれを知っているかどうかを尋ね、.get()
を使用する必要があることを確認することです。
これは、指定したタスクIDに関する情報がバックエンドにないときに.get()
がブロックするという問題を引き起こします。これは、タスクを開始して完了を待機できるようにするための仕様です。
元の質問の場合、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が記録されていないためにタスクIDが有効かどうかを知る方法がない場合にのみ機能します。
さらに明確化。
結果を保存せず、転送する であるため、AMQPバックエンドを使用して実行することはできません。
私の提案は、データベースのバックエンドに切り替えて、結果が既存のセロリモジュールの外部でクエリできるデータベースにあるようにすることです。結果データベースにタスクが存在しない場合は、IDが無効であると想定できます。