Заказ и событие для отправки счёта сохраняют одной транзакцией, а письмо отправляет фоновый обработчик outbox. Повторное создание заказа блокируют ключом идемпотентности и уникальным ограничением.
Как создавать заказы и надёжно отправлять счета
Заказ и событие для отправки счёта сохраняют одной транзакцией, а письмо отправляет фоновый обработчик outbox. Повторное создание заказа блокируют ключом идемпотентности и уникальным ограничением.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Спроектируйте сервис магазина: запрос создаёт заказ, фиксирует цены товаров и инициирует отправку клиенту счёта на оплату по email. Почтовый сервис иногда недоступен, а клиент может повторить запрос. Как избежать потери заказа и повторного создания?
Ответ
Заказ и событие для отправки счёта сохраняют одной транзакцией, а письмо отправляет фоновый обработчик outbox. Повторное создание заказа блокируют ключом идемпотентности и уникальным ограничением.
Последовательность:
- Проверить входные данные и получить доверенные цены на сервере.
- В транзакции создать заказ со снимком позиций, суммы и валюты; сохранить outbox-событие с уникальным ID.
- Зафиксировать транзакцию и вернуть ID заказа. Не держать её открытой во время обращения к почте.
- Обработчик формирует счёт из сохранённых данных, отправляет письмо и отмечает событие обработанным.
При повторном запросе с тем же ключом возвращается прежний результат; другой payload с тем же ключом — конфликт. У отправки нужны повторы с задержкой и наблюдение за окончательными ошибками. Сбой после принятия письма провайдером, но до записи статуса может дать дубль: используйте идемпотентность провайдера, если она доступна. Одного флага sent недостаточно для гарантии ровно одной доставки.