Проработка: - Прототипы интерфейсов - Контракты API (swagger) - Пользовательские сценарии (use cases) - Sequence диаграммы - Сервис лицензий, или какой-то способ модульной поставки сервисов? Может с помощью helm чартов? - UI спецификация? Обработка ошибок на UI - Система логирования бека, фронта, дебагинг, мониторинг, алертнинг - Схема деплоя. Ставимся в кластер? А что если нет кластера? Как упаковывать коробку? - Аналитика фичей по отдельности, разделить MVP на небольшие кусочки, поставлять фичи этапами - Нагрузочное тестирование Вопросы от Леши: - Оценка временных затрат - Оценка денежных затрат (человеческий ресурс от минимум до комфорт, дать диапазон с ролями, стоимостью по сотрудникам) --- ## Архитектурные решения ### ADR-001: Стратегия работы с данными PMS **Контекст:** Система интегрируется с PMS (и другими системами) для получения данных о гостях, номерах и бронированиях. Нужно определить, как работать с этими данными. #### Варианты **Вариант 1: Pass-through (запрос по требованию)** Каждый раз запрашиваем данные из PMS когда нужно. | Плюсы | Минусы | |-------|--------| | Данные всегда актуальные | Зависимость от доступности PMS | | Не нужно хранить и синхронизировать | Задержки на каждый запрос | | Нет проблем с консистентностью | Нет истории (кто был в номере вчера?) | **Вариант 2: Полная репликация** Храним копию данных, синхронизируем по событиям или периодически. | Плюсы | Минусы | |-------|--------| | Работаем автономно при падении PMS | Сложность синхронизации | | Быстрый доступ к данным | Возможны расхождения данных | | Есть история | Дублирование хранилища | **Вариант 3: Гибридный** Храним только то, что нужно для задач + кэшируем справочники. *Что храним у себя:* - Ссылку на номер/гостя (ID из PMS) - Снапшот данных на момент создания задачи (имя гостя, номер комнаты) - Историю задач с контекстом *Что запрашиваем из PMS:* - Актуальный статус номера (грязный/чистый/занят) - Текущие бронирования - Справочник номеров (с кэшированием) #### Вопросы для принятия решения 1. **Автономность** — должна ли система работать при недоступности PMS? 2. **История** — нужно ли знать "для какого гостя делали задачу месяц назад"? 3. **Частота изменений** — как часто меняются данные в PMS (заезды/выезды)? 4. **API PMS** — поддерживает ли PMS push-уведомления (webhooks) или только pull? 5. **Объём** — сколько номеров/гостей в типичном отеле? 6. **Сценарий** — горничной нужен актуальный статус номера или достаточно того, что было при создании задачи? #### Решение *Ожидает обсуждения* --- ### ADR-002: Мультитенантность **Статус:** Открыт **Контекст:** В NFR-SCALE-003 указано, что система должна поддерживать несколько отелей на одной инсталляции. Нужно определить архитектуру изоляции данных. #### Варианты **Вариант 1: Shared Database + tenant_id** Все отели в одной БД, данные разделены по `hotel_id`. | Плюсы | Минусы | |-------|--------| | Простота развёртывания | Риск утечки данных между отелями | | Легко делать кросс-отельную аналитику | Сложнее масштабировать отдельный отель | | Экономия ресурсов | Один отель может "положить" всех | **Вариант 2: Database per Tenant** Отдельная БД на каждый отель. | Плюсы | Минусы | |-------|--------| | Полная изоляция данных | Сложность управления миграциями | | Можно масштабировать независимо | Больше ресурсов | | Проще соответствовать требованиям безопасности | Сложнее кросс-отельная аналитика | **Вариант 3: Schema per Tenant** Одна БД, но отдельная schema на отель. | Плюсы | Минусы | |-------|--------| | Баланс изоляции и простоты | Ограничения PostgreSQL на количество schema | | Проще бэкапы отдельных отелей | Всё ещё shared resources | #### Вопросы для принятия решения 1. **Количество отелей** — сколько отелей планируется на одной инсталляции? 2. **Требования безопасности** — есть ли требования к физической изоляции данных? 3. **Кросс-отельная аналитика** — нужны ли отчёты по всем отелям сразу? 4. **Модель продаж** — SaaS (много мелких) или Enterprise (мало крупных)? #### Решение *Ожидает обсуждения* --- ### ADR-003: API Gateway — готовое решение или самописный **Статус:** Открыт **Контекст:** В архитектуре указан API Gateway Layer, но не определено — это готовое решение или часть кода. От этого зависит где происходит аутентификация, rate limiting, routing. #### Варианты **Вариант 1: Готовое решение (Kong / Traefik / AWS API Gateway)** | Плюсы | Минусы | |-------|--------| | Готовый rate limiting, auth, metrics | Дополнительная зависимость | | Battle-tested | Может быть избыточно для MVP | | Меньше кода | Vendor lock-in (для облачных) | **Вариант 2: Самописный на FastAPI** | Плюсы | Минусы | |-------|--------| | Полный контроль | Нужно писать и поддерживать | | Нет лишних зависимостей | Rate limiting, auth — своими руками | | Гибкость | Риск ошибок безопасности | **Вариант 3: Nginx + Lua / OpenResty** | Плюсы | Минусы | |-------|--------| | Высокая производительность | Lua — дополнительный язык | | Проверенное решение | Сложнее отлаживать | #### Вопросы для принятия решения 1. **Где аутентификация?** — Gateway проверяет JWT или каждый сервис сам? 2. **Rate limiting** — нужен ли в MVP? 3. **Инфраструктура** — есть ли уже Kubernetes Ingress / Load Balancer? 4. **Команда** — есть ли опыт с Kong/Traefik? #### Решение *Ожидает обсуждения* --- ### ADR-004: Разделение users-service и permissions-service **Статус:** Открыт **Контекст:** В архитектуре есть два отдельных сервиса: `users-service` (пользователи, профили) и `permissions-service` (RBAC, роли). Возможно это избыточно для MVP. #### Варианты **Вариант 1: Два отдельных сервиса (текущий)** | Плюсы | Минусы | |-------|--------| | Чёткое разделение ответственности | Overhead на межсервисное взаимодействие | | Можно развивать независимо | Сложнее для MVP | | Permissions можно переиспользовать | Больше точек отказа | **Вариант 2: Объединить в один auth-service** | Плюсы | Минусы | |-------|--------| | Проще для MVP | Может разрастись | | Меньше latency | Сложнее разделить потом | | Один источник правды о пользователе | — | #### Вопросы для принятия решения 1. **Сложность RBAC** — насколько сложная система прав планируется? 2. **Переиспользование** — будут ли другие системы использовать permissions-service? 3. **MVP scope** — что минимально необходимо для запуска? #### Решение *Ожидает обсуждения* --- ### ADR-005: WebSocket масштабирование **Статус:** Открыт **Контекст:** `notification-service` использует WebSocket для real-time уведомлений. При нескольких инстансах сервиса нужен механизм доставки сообщения на нужный инстанс. #### Варианты **Вариант 1: Sticky Sessions** Клиент всегда идёт на один и тот же инстанс. | Плюсы | Минусы | |-------|--------| | Просто реализовать | Неравномерная нагрузка | | Не нужен pub/sub | При падении инстанса — переподключение | **Вариант 2: Redis Pub/Sub** Все инстансы подписаны на Redis, сообщение доставляется всем. | Плюсы | Минусы | |-------|--------| | Равномерная нагрузка | Дополнительная зависимость | | Отказоустойчивость | Больше трафика | **Вариант 3: Kafka → все инстансы** Каждый инстанс читает из Kafka и отправляет своим клиентам. | Плюсы | Минусы | |-------|--------| | Уже есть Kafka | Дублирование сообщений | | Персистентность | Нужна фильтрация на клиенте | #### Вопросы для принятия решения 1. **Количество инстансов** — сколько реально будет в production? 2. **Частота сообщений** — сколько уведомлений в секунду? 3. **Критичность доставки** — что если уведомление не дошло? #### Решение *Ожидает обсуждения* --- ### ADR-006: Scheduler — гарантия единственного выполнения **Статус:** Открыт **Контекст:** `scheduler-service` создаёт задачи по расписанию. При нескольких инстансах может создать дубликаты. #### Варианты **Вариант 1: Distributed Lock (Redis/PostgreSQL)** Только один инстанс выполняет задачу. | Плюсы | Минусы | |-------|--------| | Гарантия единственности | Сложность реализации | | Отказоустойчивость | Lock может "застрять" | **Вариант 2: Leader Election** Один инстанс — лидер, остальные в standby. | Плюсы | Минусы | |-------|--------| | Простая логика в коде | Нужен механизм выбора лидера | | — | Single point of failure | **Вариант 3: Один инстанс scheduler'а** Просто не масштабируем этот сервис. | Плюсы | Минусы | |-------|--------| | Максимально просто | Нет отказоустойчивости | | — | Для MVP может быть достаточно | #### Вопросы для принятия решения 1. **Критичность** — что если задача не создалась вовремя? 2. **Частота** — как часто запускаются scheduled задачи? 3. **MVP** — нужен ли scheduler в MVP вообще? (В ROADMAP он в этапе 3) #### Решение *Ожидает обсуждения* --- ### ADR-007: Консистентность данных между сервисами **Статус:** Открыт **Контекст:** При создании задачи нужно: сохранить в БД, отправить уведомление, записать в аудит. Что если одна из операций упадёт? #### Проблемы 1. **Частичное выполнение** — задача создана, но уведомление не отправлено 2. **Дубликаты** — retry создал задачу дважды 3. **Порядок событий** — аудит записал раньше, чем задача реально создалась #### Варианты **Вариант 1: Saga Pattern** Цепочка компенсирующих транзакций. **Вариант 2: Outbox Pattern** Сначала пишем в локальную таблицу outbox, потом отдельный процесс отправляет в Kafka. **Вариант 3: Event Sourcing** Храним события, состояние вычисляется. #### Вопросы для принятия решения 1. **Критичность** — насколько критична потеря уведомления? 2. **Идемпотентность** — как обрабатывать повторные запросы? 3. **Сложность** — готовы ли усложнять архитектуру ради гарантий? #### Решение *Ожидает обсуждения* --- ### ADR-008: Жизненный цикл файлов **Статус:** Открыт **Контекст:** К задачам прикрепляются файлы (фото уборки). Нужно определить что с ними происходит при удалении/архивации задачи. #### Вопросы для принятия решения 1. **Удаление задачи** — удалять файлы или оставлять? 2. **Архивация** — нужно ли переносить старые файлы в "холодное" хранилище? 3. **Дедупликация** — один файл может быть привязан к нескольким задачам? 4. **Квоты** — есть ли лимит на размер файлов / количество на задачу? 5. **Доступ** — как генерировать URL? Presigned URLs или через API? #### Решение *Ожидает обсуждения* --- ### ADR-009: gRPC vs REST — когда что использовать **Статус:** Открыт **Контекст:** В архитектуре указаны оба протокола. Нужно определить границы применения. #### Вопросы для принятия решения 1. **Внешний API** — только REST или gRPC тоже? 2. **Межсервисное** — всё через gRPC или только критичные вызовы? 3. **Команда** — есть ли опыт с gRPC? 4. **Клиенты** — мобильные приложения будут использовать gRPC? #### Потенциальное решение - **REST** — внешний API (клиенты, адаптеры) - **gRPC** — межсервисное взаимодействие (tasks ↔ permissions) #### Решение *Ожидает обсуждения* --- ### ADR-010: Отсутствующие компоненты в архитектуре **Статус:** Открыт **Контекст:** При анализе выявлены компоненты, которые не описаны, но могут быть необходимы. #### Что не описано | Компонент | Зачем нужен | Критичность для MVP | |-----------|-------------|---------------------| | **Health checks** | Kubernetes liveness/readiness probes | Высокая | | **Circuit Breaker** | Защита от каскадных отказов | Средняя | | **Rate Limiting** | Защита от DDoS/abuse | Средняя | | **Service Discovery** | Как сервисы находят друг друга | Высокая (если не K8s) | | **Distributed Tracing** | Отладка цепочек вызовов | Низкая для MVP | | **Config Service** | Централизованная конфигурация | Низкая | | **Secret Management** | Хранение credentials | Высокая | #### Вопросы для принятия решения 1. **Kubernetes** — будет ли K8s? Если да, многое решается из коробки 2. **MVP scope** — что из этого критично для первого релиза? #### Решение *Ожидает обсуждения* --- ### ADR-011: Безопасность Kafka **Статус:** Открыт **Контекст:** Через Kafka ходят данные о задачах, гостях, бронированиях. Нужно определить уровень защиты. #### Вопросы для принятия решения 1. **Шифрование** — нужен ли TLS между сервисами и Kafka? 2. **Аутентификация** — SASL или открытый доступ внутри кластера? 3. **Авторизация** — ACL на топики (кто может читать/писать)? 4. **Сетевая изоляция** — Kafka только во внутренней сети? #### Решение *Ожидает обсуждения* --- ### ADR-012: Версионирование API **Статус:** Открыт **Контекст:** API будет развиваться. Нужна стратегия обратной совместимости. #### Варианты | Подход | Пример | Плюсы | Минусы | |--------|--------|-------|--------| | URL versioning | `/api/v1/tasks` | Явно, просто | Дублирование кода | | Header versioning | `Accept: application/vnd.api.v1+json` | Чистые URL | Сложнее тестировать | | Query parameter | `/api/tasks?version=1` | Просто | Некрасиво | #### Вопросы для принятия решения 1. **Клиенты** — кто будет потреблять API? Только свои или внешние? 2. **Частота изменений** — как часто планируются breaking changes? #### Решение *Ожидает обсуждения*