Постановку Celery-задачи нужно отложить через transaction.on_commit: воркер получит задание только после успешного commit, а не раньше появления данных в БД.
Как в Django правильно запустить асинхронную Celery-задачу внутри блока transaction.atomic, например для отправки email?
Постановку Celery-задачи нужно отложить через transaction.on_commit: воркер получит задание только после успешного commit, а не раньше появления данных в БД.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Постановку Celery-задачи нужно отложить через transaction.on_commit: воркер получит задание только после успешного commit, а не раньше появления данных в БД.
В callback передавайте идентификатор объекта, а не ORM-экземпляр. Например: transaction.on_commit(partial(send_email.delay, user.pk)), предварительно импортировав partial из functools. При rollback callback не выполнится; при вложенном atomic дождётся внешней транзакции. Для задач на базе DjangoTask в Celery 5.4+ есть delay_on_commit. Это устраняет гонку с чтением незакоммиченных данных, но не гарантирует доставку при падении процесса после commit. Для такой гарантии нужен transactional outbox и идемпотентный обработчик.
Источник: docs.celeryq.dev.