Избегайте повторных попыток Celery для незарегистрированной задачи
У нас есть приложение Django с celery для обработки асинхронных задач. Мы используем AWS SQS в качестве брокера задач.
В итоге мы получили плохо обрабатываемую задачу (удалили реализацию задачи, не удалив запись celery-beat). Это привело к ошибкам:
Received unregistered task of type KeyError('some_deleted_task').
The message has been ignored and discarded.
После очистки записей celery-beat мы продолжали получать ошибки ~2 минуты (таймаут видимости на SQS был установлен на 2 минуты).
Поведение выглядело следующим образом:
- Task added to queue, in SQS as 'Available'
- Worker picks up the task, moves the SQS message to 'in flight'
- Worker fails immediately due to missing implementation.
- two minutes later, SQS moves the message from 'in flight', back to 'available'
- Goto 2
Чтобы устранить ошибки, мы очистили очередь SQS, но это могло привести к потере других задач.
Я бы хотел настроить celery так, чтобы он не продолжал бесконечно пытаться выполнить эти отсутствующие задачи.
Celery не делает ничего, чтобы активно повторить задание. Как указано в сообщении, задача игнорируется. Задача была поставлена в очередь, и, что вполне разумно, celery не удалит ее из очереди, пока не выполнит задачу, связанную с сообщением. Наблюдаемое вами поведение правильно и желательно.
Вы не хотите, чтобы получение незарегистрированной задачи приводило к удалению сообщения из очереди, поскольку это может привести к потере сообщений. Например, если вы развертываете новую версию вашего приложения с новой задачей, но старый рабочий все еще активен (что происходит практически при всех развертываниях с нулевым временем простоя), старая версия может получать сообщения от новой версии, и она будет считать, что получила незарегистрированную задачу. Если бы celery удалял сообщения при встрече с незарегистрированными задачами, это могло бы привести к потере этих сообщений, среди прочих подобных случаев.