From a559d3848ac7d993397f4a4199a955dde1114a5d Mon Sep 17 00:00:00 2001 From: Nikolay Vigdorov Date: Tue, 13 Jan 2026 08:23:03 +0300 Subject: [PATCH] add questions --- ARCHITECTURE.md | 12 +- NOTIONS.md | 450 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 455 insertions(+), 7 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index adba1f0..cc2c4cc 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -41,7 +41,7 @@ flowchart TB subgraph AdapterLayer["Adapter Layer (Python)"] PMSAdapter["PMS Adapter"] ERPAdapter["ERP Adapter"] - HousekeepingAdapter["Housekeeping Adapter"] + ResonlineAdapter["Resonline Adapter"] TelegramAdapter["Telegram Bot Adapter"] CustomAdapter["Custom Adapter #N"] end @@ -49,7 +49,7 @@ flowchart TB subgraph ExternalSystems["External Systems"] PMS["PMS"] ERP["ERP"] - Housekeeper["Housekeeper"] + Resonline["Resonline"] end %% Client -> API Gateway @@ -88,14 +88,14 @@ flowchart TB %% Kafka <-> Adapters Kafka <--> PMSAdapter Kafka <--> ERPAdapter - Kafka <--> HousekeepingAdapter + Kafka <--> ResonlineAdapter Kafka <--> TelegramAdapter Kafka <--> CustomAdapter %% Adapters -> External Systems PMSAdapter --> PMS ERPAdapter --> ERP - HousekeepingAdapter --> Housekeeper + ResonlineAdapter --> Resonline ``` --- @@ -197,7 +197,7 @@ flowchart TB |---------|---------|----------| | PMS Adapter | Бронирования, статусы номеров, данные гостей | Запросы на изменение статуса номера | | ERP Adapter | Данные о материалах, заявки | Списания, обновления остатков | -| Housekeeping Adapter | Статусы уборки | Задачи на уборку | +| Resonline Adapter | Статусы уборки | Задачи на уборку | | Telegram Bot Adapter | Сообщения от гостей | Уведомления для отправки | ### Адаптеры → Внешние системы @@ -205,7 +205,7 @@ flowchart TB |---------|-----------------|--------| | PMS Adapter | PMS | Синхронизация бронирований и статусов номеров | | ERP Adapter | ERP | Синхронизация складских данных | -| Housekeeping Adapter | Housekeeper | Синхронизация задач уборки | +| Resonline Adapter | Resonline | Синхронизация задач уборки | --- diff --git a/NOTIONS.md b/NOTIONS.md index 7fafb5f..e392044 100644 --- a/NOTIONS.md +++ b/NOTIONS.md @@ -13,4 +13,452 @@ Вопросы от Леши: - Оценка временных затрат -- Оценка денежных затрат (человеческий ресурс от минимум до комфорт, дать диапазон с ролями, стоимостью по сотрудникам) \ No newline at end of file +- Оценка денежных затрат (человеческий ресурс от минимум до комфорт, дать диапазон с ролями, стоимостью по сотрудникам) + +--- + +## Архитектурные решения + +### 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? + +#### Решение + +*Ожидает обсуждения* \ No newline at end of file