21 KiB
type, work_item_id, title, version, status, created_at, authors
| type | work_item_id | title | version | status | created_at | authors | |
|---|---|---|---|---|---|---|---|
| infra-requirements | ET-012 | Инфраструктурные требования — ET-012: Снижение minzoom публичных треков до z5 | 1 | approved | 2026-06-04 |
|
Инфраструктурные требования — ET-012
1. Резюме
ET-012 — calibration only. Меняются три файла исходного кода
(src/api/gps_tracks/mvt.py, src/web/gps_tracks.js,
src/web/index.html) + добавляются тесты. Инфраструктура не
меняется:
- 0 новых docker-сервисов;
- 0 изменений в
Dockerfile; - 0 изменений в
docker-compose.yml; - 0 новых файлов БД, миграций, индексов;
- 0 новых cron-записей;
- 0 новых env / секретов / API-ключей;
- 0 новых исходящих HTTPS-соединений;
- 0 новых портов;
- 0 изменений в nginx (новый minzoom прозрачен для прокси).
Эскалация: minor change (см. ADR-016 §«Классификация изменения»).
2. Контейнеры и сервисы
| Аспект | Требование |
|---|---|
| Новый сервис | Нет |
Изменения Dockerfile |
Нет |
Изменения docker-compose.yml |
Нет |
Перезапуск app после деплоя |
Нужен — docker compose up -d --no-deps app (≈ 5 сек простоя). Подхватывает новую tier-таблицу в build_gps_mvt, новый _simplify_coords, обновлённые src/web/*.js / *.html |
Перезапуск gps-collector |
Не нужен — pipeline не затронут (collector только пишет в БД, отдачей не занимается) |
| Очистка серверного MVT-кэша после деплоя | Нужна — _gps_tile_cache старых тайлов z5-z7 не существует (раньше слой был скрыт), но кэш z8-z11 надо инвалидировать через POST /api/gps-tracks/cache/clear (см. §6.2) |
| Очистка клиентского кэша / Service Worker | Не нужно — gps_tracks.js подгружается с ?v=... версионным query-параметром (см. src/web/index.html загрузка модулей); пользователь получит обновлённый клиент при reload |
2.1 Зависимости между сервисами
Без изменений vs ET-008/ET-009/ET-011. Те же зависимости:
app→ файл/app/data/gps_tracks.sqlite(read-only при отдаче, read/write только изgps-collector).gps-collector→ тот же файл (offline pipeline, не затрагивается).nginx (host)→app:8000через docker-network bridge.
3. Сеть
| Аспект | Требование |
|---|---|
| Новые входящие порты | Нет |
| Изменения nginx | Нет (тот же location /enduro/api/gps-tracks/tiles/{z}/{x}/{y}.mvt; новые z=5/6/7 — это просто другие значения существующего path-параметра) |
| nginx gzip для MVT | Должен быть включён в mime.types/gzip_types для application/x-protobuf. Это уже было сделано в ET-008. Проверить при деплое (см. §6.2 шаг 3) |
| Кэш-заголовки на MVT | Без изменений — endpoint отдаёт Cache-Control: public, max-age=300 (как было). На клиенте MapLibre LRU + браузер-кэш используют это |
| Новые исходящие соединения | Нет — никаких внешних API не дёргается, всё локально |
| CORS | Без изменений; middleware уже отдаёт Access-Control-Allow-Origin: * для всего /api/ |
3.1 Ingress traffic — оценка дельты
Размер MVT-тайла z=5 ≤ 200 KB до gzip (M-8), после nginx gzip ~50-70 KB.
Сценарий «пользователь открыл карту, увидел z5, попанил по ЦФО»:
- Тайлов в кадре одновременно: ~6-10 на z5.
- Уникальных за сессию (~5 минут pan): 20-30.
- Итого ingress: 20-30 × 70 KB = ~1.5-2 MB на сессию сверх того, что было раньше (раньше на z5 запросов не было вообще — слой был скрыт).
Это допустимая дельта — uplink mva154 ≥ 100 Mbps по DuckDNS, при 10 одновременных пользователях пик ≈ 15 Mbps входящего трафика, ≈ 80 Mbps уходящего (тайлы клиенту).
3.2 Rate-limit на endpoint
Не вводим в этой итерации (BRD §3 «out of scope»). Текущий
AbortController + 500 ms debounce на клиенте (ADR-008 §D) и серверный
LRU защищают от шторма.
Если в продакшене обнаружится бот / scraper, дёргающий весь z=5
grid (1024 запроса) — добавляем slowapi-middleware отдельным
DevOps-task'ом (out of ET-012).
4. Серверные ресурсы
| Аспект | Требование |
|---|---|
CPU app |
Без изменений по архитектуре; рост нагрузки оценочно ≤ +5% при сценарии «один пользователь pan на z5» (генерация одного MVT ≤ 200 мс CPU). PERF-Z5-01 — гейт. |
RAM app |
Без изменений. _gps_tile_cache ограничен 1024 записями × max 200 KB = 200 MB max. На практике средний размер MVT z5-z11 ≈ 50 KB → ≈ 50 MB в худшем случае |
Disk app |
Без изменений. БД gps_tracks.sqlite не меняется; никаких новых файлов / volume |
CPU gps-collector |
Без изменений (pipeline не затронут) |
RAM gps-collector |
Без изменений |
Disk gps-collector |
Без изменений |
4.1 LRU cache size
_GPS_TILE_CACHE_MAX = 1024 — не меняем в MVP (ADR-016 §C).
Опционально можно поднять до 2048, если M-11 (cache hit ≥ 80%) не
будет выполняться на test-среде после деплоя. Это маленький минорный
патч (одна константа в src/api/gps_tracks/mvt.py), не требует
архитектурного решения.
5. Конфигурация и секреты
| Аспект | Требование |
|---|---|
| Новые env-переменные | Нет |
| Новые секреты | Нет |
| Новые API-ключи | Нет |
Изменения config/gps_sources.yaml |
Нет |
Изменения config/gps_regions.yaml |
Нет |
| Изменения runtime config | Нет — GPS_TRACKS_MIN_ZOOM остаётся хардкодом в src/web/gps_tracks.js (BRD §3 Out of scope: «feature-flag для minzoom не вводим») |
6. Деплой
6.1 Среды
- dev (локально):
make dev(docker compose upapp+gps-collectorс overrides). Достаточноgit pull && make devдля смены поведения. - test (mva154):
https://openclaw.mva154.duckdns.org/enduro/. CI/CD — Gitea Actions; деплой черезmake deploy-testили ручной SSH +docker compose up -d --no-deps --build app(см. §6.2). - prod — пока не задействован; ET-012 деплоится только в test.
6.2 Процедура деплоя в test
Последовательность шагов (REQ-F-19 в TRZ §3):
- Сборка образа:
docker compose build appна mva154 (послеgit pull). - Перезапуск
app:docker compose up -d --no-deps app. - Smoke-проверка nginx gzip:
Ожидается
curl -sI -H 'Accept-Encoding: gzip' \ 'https://openclaw.mva154.duckdns.org/enduro/api/gps-tracks/tiles/5/19/9.mvt' \ | grep -i 'content-encoding'content-encoding: gzip. - Очистка серверного MVT-кэша (опционально, но рекомендуется
после изменения tier-таблицы):
(Endpoint доступен только из docker-network, см. ADR-008 §7.)
curl -sX POST 'http://app:8000/api/gps-tracks/cache/clear' - Ручная валидация AC-03..AC-08, AC-09..AC-10 через DevTools.
- Запись результатов в
13-test-report.mdи14-deploy-log.md(REQ-F-19).
6.3 Rollback
В случае проблем (например, размер MVT z5 > 200 KB на реальных данных → деградация мобильного клиента):
- Backend rollback:
git revert <commit>+docker compose up -d --no-deps --build app. - Frontend rollback: тот же образ; пользователи получают старый
gps_tracks.jsпри следующем reload. - Cache invalidation после rollback:
POST /api/gps-tracks/cache/clear.
RTO: ≤ 5 минут (один docker compose up -d --no-deps app).
RPO: 0 — никаких изменений в БД, никаких данных не теряется.
6.4 CI/CD-гейты
make lint(ruff + eslint) — должен быть зелёным (AC-21).make test(pytest unit + integration) — зелёный (AC-11..AC-14, AC-21).pytest -m perf(PERF-Z5-01) — отдельный джоб, не блокирующий merge в MVP, но логируется в13-test-report.md. Если при росте БД (например, после очередногоgps-collectorrunс +500 треков) тест начинает фейлить — задача в backlog: ужесточить tier-лимиты или ввести pre-rendering (ADR-016 вариант P-B).
7. Observability / Логирование
| Аспект | Требование |
|---|---|
| Новые лог-сообщения | Нет (NFR-07 в TRZ §4) |
| Существующие лог-сообщения | uvicorn.access логирует все запросы к /api/gps-tracks/tiles/{z}/{x}/{y}.mvt с длиной ответа — этого достаточно для мониторинга размера MVT z5 |
| Метрики / Prometheus | Не вводим в MVP. Если в будущем понадобятся p95-метрики build_gps_mvt — отдельный work-item (DevOps) |
| Health-endpoint | GET /api/gps-tracks/health — без изменений; возвращает состояние БД, число треков по источникам |
7.1 Что мониторить после деплоя
В nginx access.log на mva154 (вручную, без алёртов):
- Размер ответа на
/tiles/5/*/*.mvt: средняя ≤ 80 KB (после gzip), максимум ≤ 200 KB. Если max превышает 200 KB — ужесточить tier (limit=1000вместо 1500 для z=5). - Status codes: только 200. Никаких 500/502 на z=5..7 (отлично индикатор регрессии).
- Latency p95: ≤ 700 мс cold, ≤ 50 мс hit (M-7).
Эти проверки выполняются вручную в первую неделю после деплоя; если стабильно — закрываются.
8. Резервное копирование / Disaster recovery
| Аспект | Требование |
|---|---|
| Backup БД | Без изменений — БД gps_tracks.sqlite бэкапится тем же crontab-скриптом, что и раньше (ET-008) |
| Время восстановления (RTO) | ≤ 5 минут (rollback контейнера, см. §6.3) |
| Точка восстановления (RPO) | 0 — никаких данных не теряется |
9. Безопасность
| Аспект | Требование |
|---|---|
| Auth / Authorization | Без изменений (NFR-05 в TRZ §4). Endpoint /tiles/{z}/{x}/{y}.mvt — публичный (как и был на z=8..11) |
| Валидация входных данных | Без изменений; existing 0 ≤ z ≤ 22 в get_gps_tile уже корректно пропускает z=5..7 |
| CSP | Без изменений |
| Rate-limit | Не вводим в MVP (см. §3.2) |
| TLS | Без изменений — nginx с Let's Encrypt сертификатом DuckDNS |
10. Совместимость
| Аспект | Требование |
|---|---|
API контракт /api/gps-tracks/* |
Не меняется (REQ-F-15). Старые клиенты (старый gps_tracks.js со стороны браузера, который где-то закэшировался) продолжают запрашивать z=8..11 — endpoint отвечает корректно |
| MapLibre GL JS совместимость | Без изменений; используем существующее interpolate linear zoom выражение, которое поддерживается всеми текущими версиями MapLibre |
Совместимость с centralfederal.sqlite |
Не затронуто (это другая БД, для слоя trails) |
| Совместимость с OSRM | Не затронуто (роутинг работает с OSRM-графом независимо) |
| localStorage migration | Не нужно (REQ-F-18). Существующие ключи gps-tracks-enabled, gps-tracks-activities, gps-tracks-sources, gps-tracks-color-mode — без изменений |
11. Связанные документы
01-brd.md§3 In/Out of scope, §6 Зависимости.Инфра02-trz.md§3 REQ-F-19 Деплой и валидация, §4 NFR06-adr/ADR-016-z5-tiling-policy.md§«Классификация изменения», §«Последствия»08-data-requirements.md(этот пакет)10-tech-risks.md(этот пакет)docs/work-items/ET-008/07-infra-requirements.md§3 (nginx gzip для MVT, cache-clear network policy) — наследиеdocs/work-items/ET-011/07-infra-requirements.md— образец «zero-infra» work-item