Периодические задания Celery обрабатываются, только если запрос post и get отправлен на маршрут, содержащий .delay() и AsyncResult()
Я хочу запускать это задание каждые три минуты, и вот что у меня есть
tasks.py
@shared_task
def save_hackathon_to_db():
logger.info('ran')
loop = asyncio.get_event_loop()
statuses = ['ended', 'open', 'upcoming']
loop.run_until_complete(send_data(statuses))
logger.info('ended')
settings.py
CELERY_BEAT_SCHEDULE = {
"devpost_api_task": {
"task": "backend.tasks.save_hackathon_to_db",
"schedule": crontab(minute="*/3"),
},
}
Однако он не запускается каждые 3 минуты, он запускается только тогда, когда я посылаю запрос post на адрес http://0.0.0.0:8000/hackathon/task
, а затем запрос get на адрес http://0.0.0.0:8000/hackathon/<task_id>
Это код для функций, относящихся к маршрутам соответственно
@csrf_exempt
def run_task(request):
if request.method == 'POST':
task = save_hackathon_to_db.delay()
return JsonResponse({"task_id": task.id}, status=202)
@csrf_exempt
def get_status(request, task_id):
print(task_id)
task_result = AsyncResult(task_id)
result = {
"task_id": task_id,
"task_status": task_result.status,
"task_result": task_result.result
}
return JsonResponse(result, status=200)
Мы знаем, что:
- Ваше приложение Django запущено, потому что оно может принимать запросы GET / POST
- например,
python manage.py runserver
- например,
- Ваш Celery worker (consumer) запущен, потому что он может принимать асинхронные
.delay()
запросы от приложения Django- например,
celery --app=my_proj worker --loglevel=INFO
- например,
Возможное решение 1
Проверьте, запущен ли также планировщик Celery (producer).
- например,
celery --app=my_proj beat --loglevel=INFO
Если вы не встроите планировщик в рабочий, обратите внимание, что это разные сущности. Рабочий, он же потребитель - это тот, кто будет получать/обрабатывать запрос, а планировщик, он же производитель - это тот, кто будет посылать/запускать запрос. Без работающего планировщика, конечно же, запланированные задачи не будут поставлены в очередь, и обработка не будет происходить.
Дополнительная информация о запуске планировщика здесь.
Возможное решение 2
Проверьте наличие журналов ошибок в экземпляре рабочего (потребитель). Возможно, планировщик (производитель) работает и выставляет задачи в очередь, но рабочий не может их обработать, возможно, из-за того, что реализация задачи не найдена. В этом случае обязательно укажите местоположение задачи в конфигурации приложения celery, например, celery_app.conf.update(imports=['backend.tasks'])
.
Чтобы проверить, правильно ли работает планировщик, в журналах должно быть видно, что он правильно выставляет задание в очередь каждые 3 минуты:
$ celery --app=my_proj beat --loglevel=INFO
celery beat v5.1.2 (sun-harmonics) is starting.
__ - ... __ - _
LocalTime -> 2021-09-11 01:38:05
Configuration ->
. broker -> amqp://guest:**@127.0.0.1:5672//
. loader -> celery.loaders.app.AppLoader
. scheduler -> celery.beat.PersistentScheduler
. db -> celerybeat-schedule
. logfile -> [stderr]@%INFO
. maxinterval -> 5.00 minutes (300s)
[2021-09-11 01:38:05,523: INFO/MainProcess] beat: Starting...
[2021-09-11 01:38:05,544: INFO/MainProcess] Scheduler: Sending due task backend.tasks.save_hackathon_to_db (devpost_api_task)
[2021-09-11 01:41:05,613: INFO/MainProcess] Scheduler: Sending due task backend.tasks.save_hackathon_to_db (devpost_api_task)
[2021-09-11 01:44:05,638: INFO/MainProcess] Scheduler: Sending due task backend.tasks.save_hackathon_to_db (devpost_api_task)
...