Plan MVP 1 - PlutoGr/TravelAgency GitHub Wiki
Этап 1: что осталось
Цель этапа: пользователь находит тур, оставляет заявку, общается с менеджером и подтверждает предложение. Основное сделано, описание в разделе «Как устроено сейчас» (см. Дорожная карта). Здесь только то, чего в коде пока нет.
Простой пример
Менеджер перевёл заявку в ProposalSent. В той же транзакции Booking записал в таблицу outbox событие ProposalSent со статусом Pending. Сейчас на этом всё: событие никто не читает, клиент узнаёт о предложении, только открыв заявку. После доработки фоновый обработчик прочитает событие, передаст его дальше (на этапе 2 в брокер) и поставит статус Processed.
Объём
Отправка событий outbox
- Есть: сущность
OutboxMessage, событияBookingCreated,BookingStatusChanged,ProposalSentпишутся вместе с изменением заявки. - Нет: фонового обработчика. Нужен процесс, который читает
Pending, отправляет и ставитProcessedилиFailed, с повтором. - Метрика: число событий в статусе
Pending.
Надёжность межсервисных вызовов
- Таймаут (deadline) на каждый gRPC-вызов. Сейчас
deadline: null. - Повторы с паузой и circuit breaker на gRPC-клиентах. Пакет Polly подключён в Chat, но не используется.
- Ключ идемпотентности для
POST /bookings: повтор того же запроса не создаёт вторую заявку.
Эксплуатация
- Бэкапы PostgreSQL вне сервера, ежедневно; проверка восстановления раз в месяц (#18).
- Метрики: задержка p95, доля ошибок, длина outbox. Сейчас настроена только трассировка OpenTelemetry.
- Мониторинг и алерты: сайт, контейнеры, диск (#12).
- Включить лимиты запросов на dev и сузить доверенные прокси (#32).
- Контейнеры не от root, пароль для Redis (#33).
- Ключи DataProtection Gateway хранить в volume (#158).
Данные
- Удалить колонку
Tour.ImageUrlи сохранённые адреса хранилища отдельной миграцией (#81). - Время в gRPC передавать как
google.protobuf.Timestamp(#55).
Вне объёма
Брокер сообщений, отдельный сервис уведомлений, Elasticsearch, аналитика, Kubernetes. Это этапы 2 и 3.
Безопасность (уже действует)
JWT в cookie, роли Client, Manager, Admin, HTTPS на dev, CORS по списку, маскирование персональных данных в логах Identity, сервисный токен на gRPC вместо mTLS. Подробно: Gateway, Межсервисные контракты, Секреты.
Приёмка этапа
Пользовательские сценарии:
- Регистрация и вход.
- Поиск тура и страница тура.
- Создание заявки.
- Обработка заявки менеджером до
ProposalSent. - Подтверждение и закрытие (
Confirmed,Closed).
Технические критерии:
- снимок тура Booking → Catalog по gRPC работает стабильно (деплой проверяет только, что gRPC-порт 8081 отвечает; проверки самого снимка на сервере нет);
- ошибки API в формате ProblemDetails;
- переходы статусов заявки покрыты тестами;
- события outbox доходят до статуса
Processed; - бэкап восстанавливается.
Готово, когда сценарии проходят вручную и смоук-тестами, тесты зелёные, нет открытых блокеров уровня Critical и High.
Правила версионирования API
- Ломающие изменения только под новым префиксом, например
/api/v2. - Неломающие: новые необязательные поля в запросах и ответах.