これが私の設定です:
- django 1.3
- セロリ2.2.6
- django-セロリ2.2.4
- djkombu 0.9.2
私のsettings.pyファイルには
BROKER_BACKEND = "djkombu.transport.DatabaseTransport"
つまり、データベースを使用してタスクをキューに入れているだけです。
次に、私の問題について説明します。ユーザーが開始したタスクがあり、完了するまでに数分かかる場合があります。タスクをユーザーごとに1回だけ実行したいので、タスクの結果を一時ファイルにキャッシュするので、ユーザーがタスクを再度開始した場合は、キャッシュされたファイルを返すだけです。ビュー関数に次のようなコードがあります。
task_id = "long-task-%d" % user_id
result = tasks.some_long_task.AsyncResult(task_id)
if result.state == celery.states.PENDING:
# The next line makes a duplicate task if the user rapidly refreshes the page
tasks.some_long_task.apply_async(task_id=task_id)
return HttpResponse("Task started...")
elif result.state == celery.states.STARTED:
return HttpResponse("Task is still running, please wait...")
elif result.state == celery.states.SUCCESS:
if cached_file_still_exists():
return get_cached_file()
else:
result.forget()
tasks.some_long_task.apply_async(task_id=task_id)
return HttpResponse("Task started...")
このコードはほとんど機能します。しかし、ユーザーがページをすばやくリロードすると、問題が発生します。タスクがキューに入れられてから、タスクが最終的にキューから削除されてワーカーに渡されるまでに、1〜3秒の遅延があります。この間、タスクの状態はPENDINGのままであるため、ビューロジックは重複するタスクを開始します。
必要なのは、タスクがすでにキューに送信されているかどうかを確認する方法です。これにより、タスクを2回送信することになりません。セロリでこれを行う標準的な方法はありますか?