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

Fullstack Test Shop

Что где лежит в коде, как запускается и что проверялось.
Версия 767226bf3c2f · подготовлено 7 сентября 2026

О проекте

Двойной клик и повторный webhook не должны создавать второй заказ или выдавать ещё один код. Если поставщик не ответил, нужно разобраться со старым запросом, прежде чем отправлять новый.

Каталог на Angular, API на NestJS, заказы в PostgreSQL. Оплату и выдачу обрабатывает воркер. Поставщики в демке — HTTP-моки. Есть сценарии с таймаутом, повторным webhook и восстановлением заказа.

  • Оплата и поставщики — явные моки; деньги не списываются, коды учебные.
  • До 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. Без этого флага действуют исходные контракты API.

Сборка выполняется 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, на сервер уходят готовые файлы и образы с фиксированной версией. Секреты отдельно. Логи ротируются; после изменения log options контейнер нужно пересоздать. Общий docker prune не используется.

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.

Архив материалов на языке оригинала.