Aquí está mi configuración:¿Cómo saber si una tarea ya se ha puesto en cola en django-apio?
- Django 1.3
- apio 2.2.6
- django-apio 2.2.4
- djkombu 0.9.2
En mi archivo me settings.py tiene
BROKER_BACKEND = "djkombu.transport.DatabaseTransport"
es decir, solo estoy usi ng la base de datos para cola de tareas.
Ahora a mi problema: Tengo una tarea iniciada por el usuario que podría tomar unos minutos en completarse. Quiero que la tarea solo se ejecute una vez por usuario, y almacenaré en caché los resultados de la tarea en un archivo temporal, por lo que si el usuario inicia nuevamente la tarea, simplemente devuelvo el archivo en caché. Tengo un código que se ve así en mi función de vista:
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...")
Este código casi funciona. Pero me encuentro con un problema cuando el usuario recarga rápidamente la página. Hay un retraso de 1 a 3 segundos entre el momento en que se pone en cola la tarea y cuando la tarea finalmente se retira de la cola y se entrega a un trabajador. Durante este tiempo, el estado de la tarea permanece PENDIENTE, lo que hace que la lógica de vista inicie una tarea duplicada.
Lo que necesito es una forma de saber si la tarea ya se ha enviado a la cola para que no termine enviándola dos veces. ¿Hay una forma estándar de hacer esto en el apio?
¿Puede 'kick_off_the_long_task_again()' comprobar para asegurarse de que la tarea se retiró de Pendiente? Si es así, puede ser un retraso suficiente para evitar la condición de carrera entre el usuario y el apio. –
kick_off_the_long_task_again() no da como resultado una tarea duplicada. Actualicé mi ejemplo para mostrar dónde hará el código una tarea duplicada. – cwick
Esa no era mi pregunta. ¿Puede 'kick_off_the_long_task_again()' verificar y esperar para asegurarse de que la tarea salió de Pending antes de completarse? –