Перейти к основному содержимому

Кейс сервиса

Order-сервис

HTTP-сервис заказов: сегодня — границы, построенные на валидации; цель — полноценное ядро жизненного цикла: машина состояний, идемпотентность, оптимистичная конкурентность и transactional outbox.

В разработкеРантайм бэкенда: Только локальная разработкаИсточник данных демо: Mock

Область применения
Бэкенд-кейс о создании заказов, состоянии жизненного цикла и семантике оплаты для технического демо-окружения.
Не входит в область
  • Не витрина или каталог товаров.
  • Не система управления запасами.
  • Не реальная интеграция с эквайрингом/платёжным провайдером.
Инженерный фокус
Машины состояний, транзакции, идемпотентность, оптимистичная конкурентность, transactional outbox.

Инженерный фокус

Машины состояний, транзакции, идемпотентность, оптимистичная конкурентность, transactional outbox.

Текущая реализация

  • Current

    POST /orders валидирует поле product (обрезка + непустое) и вызывает слой сервиса; GET /orders/{id} валидирует положительный целочисленный ID и необязательный флаг details. Хендлеры возвращают демонстрационный текст без персистентности.

    • HTTP-хендлеры: POST /orders, GET /orders/{id} — валидация и делегирование сервисуservices/order-service/cmd/order-service/main.gohttps://github.com/Officialsayp/zolotoy-dev-backende36b1025проверено 2026-09-17
    • Слой сервиса, формирующий демонстрационный результатservices/order-service/internal/service/order_service.gohttps://github.com/Officialsayp/zolotoy-dev-backende36b1025проверено 2026-09-17
  • Current

    В модуле есть независимые доменные модели и методы переходов, но они пока не подключены к HTTP-потоку.

    • Доменные модели и методы переходов (отдельно от HTTP-потока)services/order-service/internal/orderhttps://github.com/Officialsayp/zolotoy-dev-backende36b1025проверено 2026-09-17
  • Current

    Интеграции с хранилищем пока нет: созданные заказы не сохраняются, GET не читает из хранилища.

    • HTTP-хендлеры: POST /orders, GET /orders/{id} — валидация и делегирование сервисуservices/order-service/cmd/order-service/main.gohttps://github.com/Officialsayp/zolotoy-dev-backende36b1025проверено 2026-09-17
  • Current

    В проверенной инвентаризации автоматических бэкенд-тестов не было — тесты хендлеров/сервиса/домена входят в текущую веху, а не являются свершившимся фактом.

    • Бэкенд-роадмап: веха Service Layer в работеdocs/roadmap.mdzolotoy-dev-backende36b1025проверено 2026-09-17

Целевая архитектура

  • Target

    Независимые машины состояний заказа и оплаты с явной матрицей допустимых переходов, путями отмены и возврата и версионированными обновлениями.

    • Спецификация Order-сервиса (целевой контракт)docs/backend-specs/01_order_service.mdzolotoy-dev-frontend (this repository)проверено 2026-09-17
  • Target

    Персистентность в PostgreSQL с миграциями, надёжными созданием/чтением и транзакциями, в которых внешние вызовы провайдера остаются за пределами открытых транзакций БД.

    • Спецификация Order-сервиса (целевой контракт)docs/backend-specs/01_order_service.mdzolotoy-dev-frontend (this repository)проверено 2026-09-17
    • Веха персистентности: репозиторий PostgreSQL и миграции (будущее)docs/roadmap.mdzolotoy-dev-backende36b1025проверено 2026-09-17
  • Target

    Оптимистичная конкурентность (проверки версий) и ключи идемпотентности: повторные create/pay-операции сходятся к одному результату, а не дублируют побочные эффекты.

    • Спецификация Order-сервиса (целевой контракт)docs/backend-specs/01_order_service.mdzolotoy-dev-frontend (this repository)проверено 2026-09-17
  • Target

    Transactional outbox записывает события заказа атомарно с изменениями состояния; публикация — at-least-once, потребители дедуплицируют.

    • Спецификация Order-сервиса (целевой контракт)docs/backend-specs/01_order_service.mdzolotoy-dev-frontend (this repository)проверено 2026-09-17
    • Веха событий: контракт outbox для Notification (будущее)docs/roadmap.mdzolotoy-dev-backende36b1025проверено 2026-09-17

Архитектура / основной поток

Текущая
  • HTTP-клиентcurl / ручная коллекция Bruno
  • Хендлер (net/http)POST /orders, GET /orders/{id}: обрезка, валидация, делегирование
  • Order-сервисПостроение бизнес-результата (в разработке)
  • Доменные моделиПереходы статусов/оплаты — есть, но не подключены
  • POST /orders {product}: client → handler
  • валидированный вызов: handler → service
  • пока не интегрировано: service → domain (план)
Текущий поток заказов: HTTP-граница → слой сервиса, без хранилища.
Целевая
  • HTTP-клиентПотребители JSON API
  • ХендлерВалидация DTO и конверты ошибок
  • Order-сервисМатрица переходов, идемпотентность, проверки версий
  • PostgreSQLЗаказы, история, записи outbox
  • Издатель outboxДоставка событий at-least-once
  • JSON API: client → handler
  • граница приложения: handler → service
  • транзакционные записи: service → db (план)
  • атомарные записи событий: db → outbox (план)
Целевой поток заказов: машины состояний, персистентность, outbox.

Инженерные решения

Валидация живёт на HTTP-границе, бизнес-правила — в слое сервиса

Хендлеры обрезают и валидируют форму входных данных (product, ID, флаги) и делегируют; результат принадлежит слою сервиса. Вынос транспортного разбора из сервиса делает границу тестируемой без HTTP.

Доменные модели строятся отдельно до связывания с HTTP-потоком

Машины состояний заказа/оплаты и методы переходов разрабатываются как независимый доменный пакет, чтобы семантику жизненного цикла можно было спроектировать и протестировать до связывания с хендлерами и хранилищем.

Ключи идемпотентности привязаны к операции + payload

Целевой дизайн: повторный ключ идемпотентности с тем же payload возвращает исходный результат; тот же ключ с другим payload — клиентская ошибка. Это защищает и от дублирования побочных эффектов, и от тихой подмены payload.

Внешние платёжные вызовы остаются за пределами открытых транзакций БД

Целевой дизайн: зарезервировать состояние в короткой транзакции, вызвать провайдера вне её, затем применить результат в защищённом переходе. Падение между шагами разбирается сверкой (reconciliation), а не удержанием блокировок на время сетевого I/O.

Надёжность / сценарии отказа

Повторный ключ идемпотентности: тот же payload vs другой payload
Тот же payload → вернуть записанный результат (без второго побочного эффекта). Другой payload → клиентская ошибка вида 409 вместо тихой повторной обработки. Сохранённый ключ должен быть привязан к отпечатку запроса.
Конкурирующие операции Pay/Cancel
Два конкурентных перехода одного заказа сериализуются через проверку версии: выигрывает ровно один, проигравший получает конфликт конкурентности и перечитывает актуальное состояние.
Платёжный вызов против падения процесса
Если процесс умирает между списанием и записью результата, исход разбирает сверка (reconciliation), а не живая транзакция; заказ фиксирует состояние «платёж в обработке», а не делает вид, что ничего не было.
Дубликаты публикации outbox
Доставка outbox — at-least-once: потребители обязаны дедуплицировать по ID события. Издатели не обещают exactly-once.

Доказательства

  • HTTP-хендлеры: POST /orders, GET /orders/{id} — валидация и делегирование сервисуservices/order-service/cmd/order-service/main.gohttps://github.com/Officialsayp/zolotoy-dev-backende36b1025проверено 2026-09-17
  • Слой сервиса, формирующий демонстрационный результатservices/order-service/internal/service/order_service.gohttps://github.com/Officialsayp/zolotoy-dev-backende36b1025проверено 2026-09-17
  • Доменные модели и методы переходов (отдельно от HTTP-потока)services/order-service/internal/orderhttps://github.com/Officialsayp/zolotoy-dev-backende36b1025проверено 2026-09-17
  • Спецификация Order-сервиса (целевой контракт)docs/backend-specs/01_order_service.mdzolotoy-dev-frontend (this repository)проверено 2026-09-17
  • Бэкенд-роадмап: веха Service Layer в работеdocs/roadmap.mdzolotoy-dev-backende36b1025проверено 2026-09-17
  • Веха персистентности: репозиторий PostgreSQL и миграции (будущее)docs/roadmap.mdzolotoy-dev-backende36b1025проверено 2026-09-17
  • Веха событий: контракт outbox для Notification (будущее)docs/roadmap.mdzolotoy-dev-backende36b1025проверено 2026-09-17

Интерактивное демо

Следующая веха: Персистентность заказов

Согласовать OpenAPI/DTO, добавить репозиторий/PostgreSQL/миграции и надёжные сценарии создания/чтения.

Критерии приёмки (план):

  • Набор миграций воспроизводимо создаёт схему
  • Созданные заказы переживают перезапуск процесса