kin: BATON-002 [Research] UX Designer
This commit is contained in:
commit
057e500d5f
29 changed files with 3530 additions and 0 deletions
97
docs/adr/ADR-001-backend-stack.md
Normal file
97
docs/adr/ADR-001-backend-stack.md
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
# ADR-001: Выбор бэкенд-стека
|
||||
|
||||
**Дата:** 2026-03-20
|
||||
**Статус:** Accepted
|
||||
**Автор:** Architect Agent (Kin pipeline, BATON-001)
|
||||
|
||||
---
|
||||
|
||||
## Контекст
|
||||
|
||||
Baton — минималистичное PWA приложение экстренного сигнала. Бэкенд выполняет три задачи:
|
||||
1. Принять POST /signal от 300-400 пользователей (возможны одновременные запросы)
|
||||
2. Сохранить сигнал в SQLite
|
||||
3. Отправить уведомление в Telegram-группу через Bot API
|
||||
|
||||
Проект требует простого деплоя на один VPS, без kubernetes, без сложной инфраструктуры.
|
||||
Команда имеет опыт работы с Python/FastAPI (используется в проекте Kin).
|
||||
|
||||
Рассматривались три стека: FastAPI (Python), Express/Fastify (Node.js), Go (net/http).
|
||||
|
||||
---
|
||||
|
||||
## Варианты
|
||||
|
||||
### Вариант A: FastAPI (Python 3.11+)
|
||||
|
||||
**Плюсы:**
|
||||
- Знакомость команды (используется в Kin)
|
||||
- asyncio нативно
|
||||
- Pydantic — автоматическая валидация входных данных
|
||||
- `aiosqlite` или `sqlite3` через `run_in_executor`
|
||||
- Быстрый старт разработки
|
||||
|
||||
**Минусы:**
|
||||
- В 2-3x медленнее Go по RPS
|
||||
- Docker образ ~200-400 MB (Python runtime + зависимости)
|
||||
- bcrypt блокирует event loop — нужен `run_in_executor` (решение #1004)
|
||||
|
||||
### Вариант B: Express/Fastify (Node.js 20+)
|
||||
|
||||
**Плюсы:**
|
||||
- Единый язык с фронтендом (vanilla JS)
|
||||
- `better-sqlite3` — синхронный, самый быстрый SQLite биндинг для Node.js
|
||||
- Fastify ~24% быстрее FastAPI по RPS в независимых тестах
|
||||
- Docker образ ~200-300 MB
|
||||
|
||||
**Минусы:**
|
||||
- Нет опыта работы в команде
|
||||
- `better-sqlite3` синхронный — блокирует event loop при долгих запросах (на практике приемлемо для simple INSERT)
|
||||
- Дополнительное переключение контекста (JS для фронта, JS для бека)
|
||||
|
||||
### Вариант C: Go (net/http)
|
||||
|
||||
**Плюсы:**
|
||||
- Компилируется в единый статический бинарь ~8-15 MB (простейший деплой)
|
||||
- В 2-3x быстрее Python, ~2x быстрее Node.js
|
||||
- Горутины — нативный concurrency без event loop ограничений
|
||||
- Нет проблем с bcrypt (не блокирует горутины)
|
||||
- Cross-compile: `GOARCH=amd64 GOOS=linux go build`
|
||||
|
||||
**Минусы:**
|
||||
- Нет опыта работы в команде
|
||||
- Более длительный онбординг
|
||||
- `modernc.org/sqlite` (CGO-free): 10-100% медленнее нативного SQLite — компромисс для кросс-компиляции
|
||||
|
||||
---
|
||||
|
||||
## Решение
|
||||
|
||||
**Выбран Вариант A: FastAPI (Python 3.11+)**
|
||||
|
||||
---
|
||||
|
||||
## Обоснование
|
||||
|
||||
1. **Знакомость команды — главный фактор для минимального проекта.** FastAPI используется в Kin. Нет времени на онбординг в Go или Node.js для задачи, которая требует ~200 строк бэкенд-кода.
|
||||
|
||||
2. **Производительности FastAPI достаточно.** При нагрузке 300-400 одновременных запросов бутылочное горлышко — Telegram rate limit (20 сообщений/минуту в группу), а не скорость Python. SQLite WAL + `busy_timeout=5000` справится с 400 одновременными INSERT за ~400 мс (решения #1002, #1005).
|
||||
|
||||
3. **Pydantic даёт бесплатную валидацию** входных данных (user_id, timestamp, geo) без дополнительного кода.
|
||||
|
||||
4. **Размер деплоя приемлем.** ~300 MB Docker образ — не проблема для одного VPS сервиса.
|
||||
|
||||
5. **Вариант B отклонён:** нет опыта у команды, преимущество в скорости (+24%) несущественно при текущей нагрузке.
|
||||
|
||||
6. **Вариант C отклонён:** несмотря на превосходную производительность и минимальный деплой, отсутствие опыта в команде создаёт риск для проекта без аргументированной причины переходить на Go.
|
||||
|
||||
---
|
||||
|
||||
## Последствия
|
||||
|
||||
- Использовать `aiosqlite` для async SQLite операций (или `sqlite3` через `run_in_executor`)
|
||||
- bcrypt (если понадобится в будущем) — только через `run_in_executor` (решение #1004)
|
||||
- SQLite WAL обязателен: `busy_timeout=5000`, `synchronous=NORMAL` — вместе (решение #1005)
|
||||
- Агрегатор Telegram: реализовать в Python как background task (asyncio) или через простой in-memory буфер с `asyncio.sleep`
|
||||
- requirements.txt: `fastapi`, `uvicorn[standard]`, `aiosqlite`, `httpx` (для Telegram API)
|
||||
- Переменные окружения: `BOT_TOKEN`, `CHAT_ID`, `DB_PATH` — читать из `.env` через `python-dotenv`
|
||||
Loading…
Add table
Add a link
Reference in a new issue