baton/README.md

131 lines
5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Baton — Экстренный сигнал
PWA-приложение для отправки экстренных сигналов с геолокацией через Telegram-бота.
## Стек
- **Backend:** Python 3.12+, FastAPI, aiosqlite, httpx
- **Frontend:** Vanilla JS PWA (Service Worker, Web Push)
- **База данных:** SQLite (WAL mode)
- **Уведомления:** Telegram Bot API
## Запуск
```bash
# Зависимости
pip install -r requirements.txt
# Переменные окружения (см. .env.example)
cp .env.example .env
# Запуск
uvicorn backend.main:app --host 0.0.0.0 --port 8000
```
## Переменные окружения
| Переменная | Обязательна | Описание |
|---|---|---|
| `BOT_TOKEN` | да | Токен Telegram-бота |
| `CHAT_ID` | да | ID чата для уведомлений |
| `WEBHOOK_SECRET` | да | Секрет для верификации Telegram webhook |
| `WEBHOOK_URL` | да | Публичный URL `/api/webhook/telegram` |
| `DB_PATH` | нет | Путь к SQLite-файлу (по умолчанию `baton.db`) |
| `FRONTEND_ORIGIN` | нет | Разрешённый origin для CORS (по умолчанию `http://localhost:3000`) |
| `WEBHOOK_ENABLED` | нет | Регистрировать webhook при старте (по умолчанию `true`) |
| `APP_URL` | нет | Публичный URL приложения для keep-alive (например `https://baton.fly.dev`) |
## API
| Метод | Путь | Описание |
|---|---|---|
| `GET` | `/health` | Health check: `{"status": "ok", "timestamp": <unix_ts>}` |
| `POST` | `/api/register` | Регистрация пользователя |
| `POST` | `/api/signal` | Отправка экстренного сигнала |
| `POST` | `/api/webhook/telegram` | Telegram webhook |
## Hosting & Keep-Alive
### Проблема cold start
На бесплатных хостингах (Render, fly.io free tier, Railway и подобных) приложение **засыпает** после периода неактивности (обычно 1530 минут). Следующий входящий запрос ждёт пока процесс поднимется заново — **cold start занимает 35 секунд**. Для экстренного приложения это критично.
### Решения по вариантам хостинга
| Вариант | Стоимость | Cold start | Рекомендация |
|---|---|---|---|
| **fly.io Hobby** | $5/мес | Нет (всегда активен) | Оптимально для прода |
| **fly.io free tier** | Бесплатно | 35 сек | Только для разработки |
| **Render free** | Бесплатно | 35 сек | Только для разработки |
| **Самохостинг (VPS)** | От $35/мес | Нет | Полный контроль |
> **Финальный выбор хостинга зависит от решения по OQ-004** (открытый вопрос по бюджету и масштабированию проекта).
### Keep-alive механизм (asyncio background task)
Приложение запускает фоновый asyncio-таск, который каждые **10 минут** пингует собственный `/health` endpoint. Это предотвращает засыпание на платформах, которые реагируют на активность процесса.
**Активация:** установите переменную `APP_URL`:
```bash
APP_URL=https://your-app.fly.dev
```
Без `APP_URL` таск не запускается (keep-alive отключён).
**Ограничение:** self-ping работает пока процесс жив. Если платформа убивает процесс при нулевом трафике — нужен внешний пингер (см. ниже).
### Keep-alive для самохостинга (cron / systemd timer)
Если приложение на VPS и нужен мониторинг извне:
**Вариант 1 — crontab:**
```bash
# Редактируем cron
crontab -e
# Добавляем запись (каждые 10 минут):
*/10 * * * * curl -sf https://your-app.example.com/health > /dev/null
```
**Вариант 2 — systemd timer:**
Создайте два файла:
`/etc/systemd/system/baton-keepalive.service`:
```ini
[Unit]
Description=Baton keep-alive ping
[Service]
Type=oneshot
ExecStart=curl -sf https://your-app.example.com/health
```
`/etc/systemd/system/baton-keepalive.timer`:
```ini
[Unit]
Description=Run Baton keep-alive every 10 minutes
[Timer]
OnBootSec=1min
OnUnitActiveSec=10min
[Install]
WantedBy=timers.target
```
Активация:
```bash
systemctl daemon-reload
systemctl enable --now baton-keepalive.timer
systemctl list-timers baton-keepalive.timer
```
## Тесты
```bash
pip install -r requirements-dev.txt
pytest
```