Как отправляются события об изменении статусов?
Что проверяют
За вопросом обычно стоит проблема двойной записи: статус обновился в базе, а событие в брокер не ушло, или наоборот. Интервьюер ждёт, что вы её назовёте и предложите transactional outbox. Следом спрашивают про порядок событий и повторную доставку.
Как отвечать
Коротко опишите, как это устроено в вашем проекте, а потом разберите надёжную схему:
- transactional outbox: в одной транзакции меняется статус в
ordersи вставляется строка в таблицуoutboxс телом события. Воркер на Go забирает неотправленные строки черезSELECT ... FOR UPDATE SKIP LOCKED, публикует их в брокер и помечает отправленными. Вместо воркера можно взять CDC через Debezium, который читает WAL и сам публикует записи outbox; - гарантии доставки: получается at-least-once, дубли неизбежны. У каждого события есть
event_id, потребитель запоминает обработанные идентификаторы или делает обработку идемпотентной; - порядок: в Kafka он гарантирован только внутри партиции, поэтому ключом сообщения берут идентификатор заказа, и все его статусы попадают в одну партицию. Поле
versionпомогает потребителю отбросить устаревший переход; - состав события: идентификатор сущности, старый и новый статус, время, версия схемы. Формат JSON или Protobuf со Schema Registry;
- ошибки: повторы с экспоненциальной задержкой, после нескольких неудач сообщение уходит в DLQ.
Клиенты на Go: для Kafka franz-go или segmentio/kafka-go, для RabbitMQ rabbitmq/amqp091-go. Внешним системам события часто отдают вебхуками с подписью HMAC и повторами. Каналы подходят только внутри одного процесса: при рестарте всё, что в них лежало, теряется.
Где спотыкаются
Публикуют событие из хендлера сразу после COMMIT. Процесс упал между коммитом и отправкой: событие потеряно. Отправили до коммита, а транзакция откатилась: ушло событие о статусе, которого в базе нет.
Обещают exactly-once. На уровне бизнес-логики его дают идемпотентные потребители, а не одна настройка брокера.
Берут streadway/amqp: библиотека больше не поддерживается, её преемник rabbitmq/amqp091-go.