Техническая документация

Fullstack Test Shop

Архитектура, сценарии, code-map и эксплуатация.
Версия 767226bf3c2f · подготовлено 7 сентября 2026

Назначение и границы

Повторный клик, повтор webhook и сбой поставщика не должны создавать второй заказ или повторную выдачу. Состояние операции должно оставаться понятным покупателю и оператору.

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

  • Оплата и поставщики — явные моки; деньги не списываются, коды учебные.
  • До 20 заказов на сессию и 1000 новых демонстрационных заказов суммарно. TTL один час, очистка каждые пять минут.
  • Пример восстановления намеренно завершает первую попытку одного заказа ошибкой. Он не меняет глобальные режимы поставщиков.

Архитектура и схемы

  • Цена и скидка вычисляются на сервере и фиксируются в заказе.
  • Idempotency-Key защищён уникальным индексом; входные данные повтора сверяются с исходным намерением.
  • Webhook сначала сохраняется в durable inbox. Отдельный worker обрабатывает платёж и очередь выдачи.
  • Стабильный requestId поставщика сохраняется при повторе. Неоднозначный timeout не разрешает немедленно выдать второй код.
Компоненты опубликованного демо
Компоненты опубликованного демо · Mermaid ↓
Основной сценарий
Основной сценарий · Mermaid ↓
Размещение опубликованной версии
Размещение опубликованной версии · Mermaid ↓
Состав данных и границы хранения
Состав данных и границы хранения · Mermaid ↓

Code-map: от функции к коду

Карта привязана к версии 767226bf3c2f. Она помогает проследить изменение через интерфейс, API, модуль, данные и проверку.

ФункцияЭкран / APIМодульДанные / проверка
ПокупкаStorefront / POST ordersstorefront.component; ShopService.createOrderorders, products, promocodes; race tests
ОплатаPOST payments/simulate → webhooks/paymentPaymentsController; acceptWebhookpayment_events; повтор event_id
ВыдачаOrder / GET orders/:idworker.service processDeliveryJobdelivery_jobs, provider_requests, fulfillments; recovery
СессияGuard всех публичных заказовportfolio-demo PortfolioGuardHMAC cookie, prefix owner; tests/portfolio/run.ts
Сброс / TTLPOST demo/reset / timerPortfolioCleanup.clearтолько portfolio orders; ownership / expiry tests

Как работать с картой

  1. Перед изменением найти функцию и пройти связи до API, состояния и хранилища.
  2. Проверить входы, ошибки, повторные события и зависимые сценарии.
  3. После изменения обновить карту и затронутые схемы вместе с кодом.
  4. Выполнить связанные проверки и привязать новые материалы к версии исходников.

Сценарии и API

  1. Выберите товар и выполните успешную тестовую оплату. Дождитесь кода и просмотрите историю.
  2. Повторите то же платёжное событие: код и выдача должны остаться единственными.
  3. Создайте заказ через сценарий сбоя, оплатите и нажмите «Восстановить мой заказ».
  4. Проверьте отказ оплаты, чужой UUID в другой сессии и сброс своего примера.

Проверка опубликованной версии

CI: CI ↗ · 767226bf · версия этого демо · 2026-09-07T00:49:05Z

CI: Portfolio immutable image ↗ · 767226bf · версия этого демо · 2026-09-07T00:49:05Z

  • Real HTTP webhook, durable inbox, worker, single fulfillment preserved on event replay
  • Foreign GET/recover return 404; other session reset preserves first order
  • Payment failure; isolated first-attempt delivery fault; own recovery succeeds

Результаты описывают проверенные сценарии и конкретную версию. Они не являются оценкой коммерческого успеха или качества моделей на независимой выборке.

Измерения

Суммарные ресурсы контейнеров проекта · 2026-09-07T01:08:27 — 01:11:22 UTC
Суммарные ресурсы контейнеров проекта · 2026-09-07T01:08:27 — 01:11:22 UTC · Исходные данные ↓
Измеренные повторения сценария через HTTPS · 2026-09-07T01:08:36 UTC; ограничения методики в JSON
Измеренные повторения сценария через HTTPS · 2026-09-07T01:08:36 UTC; ограничения методики в JSON · Исходные данные ↓
  • Сохранено 14 содержательных кадров фактического интерфейса.
  • Дата, сценарий и версия указаны у каждого кадра.
  • Максимум RAM контейнеров в коротком тесте: 218.56 MiB. Общие службы учитываются отдельно; магазин включает свою БД.
  • Измерено 6 повторений сценария; медиана 129.0 мс, максимум 1939 мс. Время включает браузер и HTTPS; методика и ограничения приложены.

Запуск и эксплуатация

Исходный и публичный контуры используют одну бизнес-модель. Демонстрационный guard включается только PORTFOLIO_DEMO=true; вне этого режима исходные контракты сохраняются.

Сборка выполняется GitHub Actions из закреплённого commit SHA. На VPS загружается готовый GHCR-образ. База магазина остаётся отдельной от новых приложений.

Запуск: docker compose --env-file .env.production -f compose.production.yaml up -d. До переключения выполнить prisma migrate deploy. Секреты хранятся только на сервере. Seed нельзя использовать как безусловный сброс данных работающего магазина.

Readiness: /api/health/ready проверяет PostgreSQL. Во время инцидента сравнить историю заказа, inbox и delivery job; повторять выдачу по исходному orderId, не создавать новую покупку.

Общие правила эксплуатации: готовые файлы и закреплённые образы собираются вне VPS; секреты не входят в артефакты. Общесерверный docker prune не применяется. Логи backend ограничены ротацией, изменения log options требуют пересоздания контейнера.

Перед изменением пройти code-map от функции к экрану/API, модулю и данным. После изменения обновить карту и схемы, выполнить связанные сценарии, включая ошибку, повтор и сброс. Источник истины — конкретная версия кода, а не старая диаграмма.

Откат проверен 2026-09-07T01:07:46.255650+00:00: 20260907-verified → 20260907 → 20260907-verified. После каждого переключения подтверждены HTTPS, readiness и SHA. Это проверка конфигурации и артефактов на одном проверенном SHA; обратная миграция БД не выполнялась.

Стек

Angular / TypeScriptВитрина, сигналы состояния, HTTP-клиент и polling заказа.
NestJSКонтракты, валидация, webhook, операции восстановления и границы демо.
PostgreSQL / PrismaСнимки денег, inbox, очередь с lease, уникальные индексы и транзакции.
Node.js workerHTTP-вызовы поставщиков вне короткой транзакции, retry и финальная выдача.

Материалы и исходники

История реализации: 1–3 сентября 2026. Подготовка портфолио: 7 сентября 2026.