20 KiB
Проработка:
- Прототипы интерфейсов
- Контракты API (swagger)
- Пользовательские сценарии (use cases)
- Sequence диаграммы
- Сервис лицензий, или какой-то способ модульной поставки сервисов? Может с помощью helm чартов?
- UI спецификация? Обработка ошибок на UI
- Система логирования бека, фронта, дебагинг, мониторинг, алертнинг
- Схема деплоя. Ставимся в кластер? А что если нет кластера? Как упаковывать коробку?
- Аналитика фичей по отдельности, разделить MVP на небольшие кусочки, поставлять фичи этапами
- Нагрузочное тестирование
Вопросы от Леши:
- Оценка временных затрат
- Оценка денежных затрат (человеческий ресурс от минимум до комфорт, дать диапазон с ролями, стоимостью по сотрудникам)
Архитектурные решения
ADR-001: Стратегия работы с данными PMS
Контекст: Система интегрируется с PMS (и другими системами) для получения данных о гостях, номерах и бронированиях. Нужно определить, как работать с этими данными.
Варианты
Вариант 1: Pass-through (запрос по требованию)
Каждый раз запрашиваем данные из PMS когда нужно.
| Плюсы | Минусы |
|---|---|
| Данные всегда актуальные | Зависимость от доступности PMS |
| Не нужно хранить и синхронизировать | Задержки на каждый запрос |
| Нет проблем с консистентностью | Нет истории (кто был в номере вчера?) |
Вариант 2: Полная репликация
Храним копию данных, синхронизируем по событиям или периодически.
| Плюсы | Минусы |
|---|---|
| Работаем автономно при падении PMS | Сложность синхронизации |
| Быстрый доступ к данным | Возможны расхождения данных |
| Есть история | Дублирование хранилища |
Вариант 3: Гибридный
Храним только то, что нужно для задач + кэшируем справочники.
Что храним у себя:
- Ссылку на номер/гостя (ID из PMS)
- Снапшот данных на момент создания задачи (имя гостя, номер комнаты)
- Историю задач с контекстом
Что запрашиваем из PMS:
- Актуальный статус номера (грязный/чистый/занят)
- Текущие бронирования
- Справочник номеров (с кэшированием)
Вопросы для принятия решения
- Автономность — должна ли система работать при недоступности PMS?
- История — нужно ли знать "для какого гостя делали задачу месяц назад"?
- Частота изменений — как часто меняются данные в PMS (заезды/выезды)?
- API PMS — поддерживает ли PMS push-уведомления (webhooks) или только pull?
- Объём — сколько номеров/гостей в типичном отеле?
- Сценарий — горничной нужен актуальный статус номера или достаточно того, что было при создании задачи?
Решение
Ожидает обсуждения
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 |
Вопросы для принятия решения
- Количество отелей — сколько отелей планируется на одной инсталляции?
- Требования безопасности — есть ли требования к физической изоляции данных?
- Кросс-отельная аналитика — нужны ли отчёты по всем отелям сразу?
- Модель продаж — 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 — дополнительный язык |
| Проверенное решение | Сложнее отлаживать |
Вопросы для принятия решения
- Где аутентификация? — Gateway проверяет JWT или каждый сервис сам?
- Rate limiting — нужен ли в MVP?
- Инфраструктура — есть ли уже Kubernetes Ingress / Load Balancer?
- Команда — есть ли опыт с Kong/Traefik?
Решение
Ожидает обсуждения
ADR-004: Разделение users-service и permissions-service
Статус: Открыт
Контекст:
В архитектуре есть два отдельных сервиса: users-service (пользователи, профили) и permissions-service (RBAC, роли). Возможно это избыточно для MVP.
Варианты
Вариант 1: Два отдельных сервиса (текущий)
| Плюсы | Минусы |
|---|---|
| Чёткое разделение ответственности | Overhead на межсервисное взаимодействие |
| Можно развивать независимо | Сложнее для MVP |
| Permissions можно переиспользовать | Больше точек отказа |
Вариант 2: Объединить в один auth-service
| Плюсы | Минусы |
|---|---|
| Проще для MVP | Может разрастись |
| Меньше latency | Сложнее разделить потом |
| Один источник правды о пользователе | — |
Вопросы для принятия решения
- Сложность RBAC — насколько сложная система прав планируется?
- Переиспользование — будут ли другие системы использовать permissions-service?
- MVP scope — что минимально необходимо для запуска?
Решение
Ожидает обсуждения
ADR-005: WebSocket масштабирование
Статус: Открыт
Контекст:
notification-service использует WebSocket для real-time уведомлений. При нескольких инстансах сервиса нужен механизм доставки сообщения на нужный инстанс.
Варианты
Вариант 1: Sticky Sessions
Клиент всегда идёт на один и тот же инстанс.
| Плюсы | Минусы |
|---|---|
| Просто реализовать | Неравномерная нагрузка |
| Не нужен pub/sub | При падении инстанса — переподключение |
Вариант 2: Redis Pub/Sub
Все инстансы подписаны на Redis, сообщение доставляется всем.
| Плюсы | Минусы |
|---|---|
| Равномерная нагрузка | Дополнительная зависимость |
| Отказоустойчивость | Больше трафика |
Вариант 3: Kafka → все инстансы
Каждый инстанс читает из Kafka и отправляет своим клиентам.
| Плюсы | Минусы |
|---|---|
| Уже есть Kafka | Дублирование сообщений |
| Персистентность | Нужна фильтрация на клиенте |
Вопросы для принятия решения
- Количество инстансов — сколько реально будет в production?
- Частота сообщений — сколько уведомлений в секунду?
- Критичность доставки — что если уведомление не дошло?
Решение
Ожидает обсуждения
ADR-006: Scheduler — гарантия единственного выполнения
Статус: Открыт
Контекст:
scheduler-service создаёт задачи по расписанию. При нескольких инстансах может создать дубликаты.
Варианты
Вариант 1: Distributed Lock (Redis/PostgreSQL)
Только один инстанс выполняет задачу.
| Плюсы | Минусы |
|---|---|
| Гарантия единственности | Сложность реализации |
| Отказоустойчивость | Lock может "застрять" |
Вариант 2: Leader Election
Один инстанс — лидер, остальные в standby.
| Плюсы | Минусы |
|---|---|
| Простая логика в коде | Нужен механизм выбора лидера |
| — | Single point of failure |
Вариант 3: Один инстанс scheduler'а
Просто не масштабируем этот сервис.
| Плюсы | Минусы |
|---|---|
| Максимально просто | Нет отказоустойчивости |
| — | Для MVP может быть достаточно |
Вопросы для принятия решения
- Критичность — что если задача не создалась вовремя?
- Частота — как часто запускаются scheduled задачи?
- MVP — нужен ли scheduler в MVP вообще? (В ROADMAP он в этапе 3)
Решение
Ожидает обсуждения
ADR-007: Консистентность данных между сервисами
Статус: Открыт
Контекст: При создании задачи нужно: сохранить в БД, отправить уведомление, записать в аудит. Что если одна из операций упадёт?
Проблемы
- Частичное выполнение — задача создана, но уведомление не отправлено
- Дубликаты — retry создал задачу дважды
- Порядок событий — аудит записал раньше, чем задача реально создалась
Варианты
Вариант 1: Saga Pattern
Цепочка компенсирующих транзакций.
Вариант 2: Outbox Pattern
Сначала пишем в локальную таблицу outbox, потом отдельный процесс отправляет в Kafka.
Вариант 3: Event Sourcing
Храним события, состояние вычисляется.
Вопросы для принятия решения
- Критичность — насколько критична потеря уведомления?
- Идемпотентность — как обрабатывать повторные запросы?
- Сложность — готовы ли усложнять архитектуру ради гарантий?
Решение
Ожидает обсуждения
ADR-008: Жизненный цикл файлов
Статус: Открыт
Контекст: К задачам прикрепляются файлы (фото уборки). Нужно определить что с ними происходит при удалении/архивации задачи.
Вопросы для принятия решения
- Удаление задачи — удалять файлы или оставлять?
- Архивация — нужно ли переносить старые файлы в "холодное" хранилище?
- Дедупликация — один файл может быть привязан к нескольким задачам?
- Квоты — есть ли лимит на размер файлов / количество на задачу?
- Доступ — как генерировать URL? Presigned URLs или через API?
Решение
Ожидает обсуждения
ADR-009: gRPC vs REST — когда что использовать
Статус: Открыт
Контекст: В архитектуре указаны оба протокола. Нужно определить границы применения.
Вопросы для принятия решения
- Внешний API — только REST или gRPC тоже?
- Межсервисное — всё через gRPC или только критичные вызовы?
- Команда — есть ли опыт с gRPC?
- Клиенты — мобильные приложения будут использовать 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 | Высокая |
Вопросы для принятия решения
- Kubernetes — будет ли K8s? Если да, многое решается из коробки
- MVP scope — что из этого критично для первого релиза?
Решение
Ожидает обсуждения
ADR-011: Безопасность Kafka
Статус: Открыт
Контекст: Через Kafka ходят данные о задачах, гостях, бронированиях. Нужно определить уровень защиты.
Вопросы для принятия решения
- Шифрование — нужен ли TLS между сервисами и Kafka?
- Аутентификация — SASL или открытый доступ внутри кластера?
- Авторизация — ACL на топики (кто может читать/писать)?
- Сетевая изоляция — 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 |
Просто | Некрасиво |
Вопросы для принятия решения
- Клиенты — кто будет потреблять API? Только свои или внешние?
- Частота изменений — как часто планируются breaking changes?
Решение
Ожидает обсуждения