Avito.Кухня — заказ от клиента до статуса

Avito.Кухня — заказ от клиента до статуса An architecture diagram generated by Archify. Клиент · POST /orders · Architecture component Клиент POST /orders kitchen-service · handler→usecase→repo, Relay · kitchen-service · kitchen kitchen-service handler→usecase→repo, Relay kitchen Postgres kitchen · orders + outbox · kitchen-service · kitchen Postgres kitchen orders + outbox kitchen kitchen-service · consumer · kitchen-service · kitchen kitchen-service consumer kitchen orders.new · key=order_id · Architecture component orders.new key=order_id orders.status_updated · key=order_id · Architecture component orders.status_updated key=order_id orders.status_updated.dlq · domain errors · Architecture component orders.status_updated.dlq domain errors establishment-service · handler→usecase→repo · establishment-service · establishment establishment-service handler→usecase→repo establishment Postgres establishment · orders copy · establishment-service · establishment Postgres establishment orders copy establishment Человек · демо-UI · Architecture component Человек демо-UI создать заказ заказ + outbox, 1 tx Relay публикует после коммита consume store POST /advance publish, key=order:status consume FOR UPDATE, no-op если статус тот же домен. ошибка, commit offset kitchen-service establishment-service Legend Backend Database Message bus External

Идемпотентность

  • • Клиентский Idempotency-Key на POST /orders — UNIQUE(user_id, key)
  • • Детерминированный key="order_id:status" на публикации статуса
  • • FOR UPDATE + сравнение статуса — no-op при повторе, ключ не нужен

Обработка ошибок consumer'а

  • • Доменная ошибка (невалидный переход) — в DLQ, offset коммитится
  • • Транзиентная ошибка (БД недоступна) — retry с backoff, offset НЕ коммитится
  • • Партиционирование по order_id — порядок гарантирован только внутри одного заказа

Транзакционность

  • • Заказ + outbox-строка — одна транзакция в kitchen_db
  • • Relay публикует ТОЛЬКО после коммита — at-least-once, не потеря
  • • Списание остатка: сортировка item_id + атомарный UPDATE...WHERE stock>=qty

Что есть что

  • • Клиент — реальный пользователь Avito, отправляет POST /orders на создание заказа
  • • kitchen-service — Go-сервис заказов: принимает заказ, списывает остаток, публикует событие в Kafka
  • • Postgres kitchen — БД сервиса заказов: таблицы orders, items, outbox (заказ и outbox пишутся одной транзакцией)
  • • kitchen-service (consumer) — тот же сервис, вторая роль: слушает статусы из Kafka и применяет их к заказу
  • • orders.new — топик Kafka, через который заказ передаётся заведению после того, как он реально сохранён в БД
  • • orders.status_updated — топик Kafka, которым заведение сообщает kitchen-service о смене статуса заказа
  • • orders.status_updated.dlq — топик-"отстойник" для статусов, которые технически невозможно применить (dead-letter queue)
  • • establishment-service — Go-сервис заведения: получает заказы, отдаёт человеку интерфейс менять их статус
  • • Postgres establishment — своя отдельная БД заведения, хранит копию заказа со своей стороны
  • • Человек — сотрудник заведения (или демо-интерфейс за него), вручную двигает статус заказа кнопкой /advance