Files
enduro-trails/docs/work-items/ET-009/07-infra-requirements.md
claude-bot 4be7fbf3de
Some checks failed
CI / lint (push) Failing after 4s
CI / test (push) Failing after 6s
CI / build (push) Has been skipped
feat(ET-009): architect deliverables — ADR, infra requirements, data requirements, tech risks, wikiloc parser stub
2026-06-01 19:20:15 +00:00

16 KiB
Raw Blame History

type, work_item_id, title, version, status, created_at, authors
type work_item_id title version status created_at authors
infra-requirements ET-009 Инфраструктурные требования — ET-009: Активация EnduroRussia + Wikiloc 1 approved 2026-06-01
agent:architect

Инфраструктурные требования — ET-009

1. Резюме

ET-009 — конфиг-only активация двух дополнительных источников GPS-треков в pipeline ET-008. Инфраструктура не меняется:

  • Никаких новых docker-сервисов;
  • Никаких новых файлов БД;
  • Никаких новых cron-записей (cron автоматизация — отдельный DevOps-task);
  • Никаких новых env-переменных, секретов, ключей;
  • Никаких новых портов и nginx-правил.

Все изменения — текстовые правки конфигов и тестовых артефактов плюс один ручной первый прогон pipeline на mva154.

Эскалация: minor change (см. ADR-013 §«Классификация»).

2. Контейнеры и сервисы

Аспект Требование
Новый сервис gps-collector Уже существует (ET-008). Без изменений.
Изменения Dockerfile Нет
Изменения docker-compose.yml Нет
Перезапуск API после деплоя Нужен — docker compose up -d --no-deps app (≈ 5 сек простоя). Перезапуск нужен только потому, что src/web/*.json подаётся API-контейнером; обновлённые style.json / style-dark.json подхватываются после рестарта
Перезапуск gps-collector Не applicable (не daemon). Следующий запуск через docker compose --profile batch run --rm gps-collector ... уже использует новый конфиг через примонтированный config/ volume

2.1 Зависимости между сервисами

Без изменений vs ET-008. gps-collectorapp коммуницируют через docker-internal HTTP при cache-clear; этот контракт уже существует и ET-009 его не трогает.

3. Сеть

Аспект Требование
Новые входящие порты Нет
Изменения nginx Нет
Новые исходящие HTTPS-соединения с mva154 Да — две новых dest: endurorussia.ru (443) и www.wikiloc.com (443)
Firewall mva154 Исходящие HTTPS уже разрешены (ET-008 §3, BRD §7). Дополнительных правил не нужно
DNS-резолвинг Стандартный (системный resolver Docker). Никаких записей в /etc/hosts

3.1 Изменение dest IP

Перед ET-009 контейнер gps-collector обращался только к:

  • api.openstreetmap.org (ADR-009);

После ET-009 добавляются:

  • endurorussia.ru (ADR-010 accepted);
  • www.wikiloc.com (ADR-012 accepted).

Все три — стандартный HTTPS, без проксей и кастомных сертификатов.

3.2 Ограничение rate

Источник Rate-limit Trafic за прогон Пик
OSM 1 req/sec ≈ 100 МБ без изменений
EnduroRussia 5 sec / req ≈ 30 МБ (≤ 305 треков × ~50 КБ + json list) 1 req / 5 сек
Wikiloc 10 sec / req ≈ 5 МБ (≤ 50 треков × 3 req × ~30 КБ) 1 req / 10 сек
Итого пиковый egress mva154 ≈ 0.1 req/sec суммарно ≤ 150 МБ / прогон пренебрежимо

Влияния на пропускную способность mva154 нет.

4. Хранилища данных

Аспект Требование
Новые БД Нет
Изменения схемы Нет
Миграции Нет
Изменения объёма data/gps_tracks.sqlite +2050 МБ ожидаемо (≤ 200 треков EnduroRussia × ~50 КБ + ≤ 50 треков Wikiloc × ~50 КБ + метаданные)
Лимит REQ-NF-03 (08-data-requirements.md ET-008) 2 ГБ — далеко не достигнут
Backup .sqlite Без изменений (тот же cron-скрипт, см. ET-008 §4.4)

4.1 Опциональный one-shot fix старого URL

Если в БД test-сервера остались записи с старым external_url (с дефисом enduro-russia.ru) — оператор может выполнить один раз после первого прогона ET-009:

UPDATE tracks
SET external_urls_json = REPLACE(external_urls_json,
                                  'enduro-russia.ru',
                                  'endurorussia.ru')
WHERE external_urls_json LIKE '%enduro-russia.ru%';

На практике, поскольку до ET-009 enduro_russia был enabled: false, таких записей нет. Скрипт — defensive, не обязательный (BRD R-9).

4.2 Backup retention

Без изменений. Ежедневный snapshot, 14 дней retention.

5. Конфигурация и секреты

Аспект Требование
Новые env-переменные Нет
Новые секреты / API-ключи Нет (EnduroRussia и Wikiloc — без авторизации)
Новые конфиг-файлы Нет; меняется только содержимое существующих config/gps_sources.yaml и config/gps_regions.yaml

5.1 Изменения config/gps_sources.yaml

См. ADR-013 §«Решение 2» — финальное содержимое. Изменения:

  • enduro_russia.base_url: https://enduro-russia.ruhttps://endurorussia.ru (без дефиса);
  • enduro_russia.enabled: falsetrue;
  • enduro_russia.source_priority: добавлено 80 (раньше отсутствовало, default fall-back в коде);
  • новая запись wikiloc (15 строк).

5.2 Изменения config/gps_regions.yaml

См. ADR-013 §«Решение 3». В tsfo_plus_chuvashia.sources добавляется wikiloc.

6. Зависимости

Аспект Требование
Новые Python-пакеты Нет (defusedxml, httpx, shapely, pyyaml — все есть из ET-008)
Системные библиотеки в Dockerfile Нет
Версия Python 3.12, без изменений
Внешние runtime-зависимости (источники) endurorussia.ru + www.wikiloc.com (см. §3.1)
Pinned-версии библиотек Без изменений

7. Сборка и деплой

7.1 Pipeline CI

Существующий Gitea Actions:

  • make lint (ruff + eslint) — должен пройти без замечаний;
  • make test — должен включать новые тесты UT-ER-, UT-WL-, IT-*;
  • make build — пересобирает образ (никаких изменений в Dockerfile, но новые тестовые фикстуры и конфиги попадают в образ).

7.2 Деплой шаг-за-шагом

  1. git pull origin main на mva154.
  2. docker compose build (опционально; никаких изменений в Dockerfile/requirements не было, но сборка идемпотентна и быстрая).
  3. docker compose up -d --no-deps app — рестарт API (≈ 5 сек простоя) для подхвата обновлённых style.json / style-dark.json и client-side JS (если изменился gps_tracks.js).
  4. Первый ручной прогон EnduroRussia:
    docker compose --profile batch run --rm gps-collector \
        python -m scripts.gps_collect \
        --region tsfo_plus_chuvashia --source enduro_russia
    
    Ожидаемая длительность: 2030 минут. Ожидаемый результат: tracks_new ≥ 200, status: ok.
  5. Первый ручной прогон Wikiloc:
    docker compose --profile batch run --rm gps-collector \
        python -m scripts.gps_collect \
        --region tsfo_plus_chuvashia --source wikiloc
    
    Ожидаемая длительность: 1025 минут (cap max_tracks_per_run=50). Ожидаемый результат: tracks_new ≥ 1, status: ok | partial.
  6. Проверить /api/gps-tracks/healthtracks_by_source содержит ключи enduro_russia и wikiloc с ненулевыми значениями.
  7. Smoke в UI: открыть /enduro/, включить «Публичные треки», проверить три чекбокса источников и атрибуции.
  8. Зафиксировать результат в docs/work-items/ET-009/14-deploy-log.md.

7.3 Время простоя

API: ≤ 5 секунд на шаге 3 (стандартный рестарт контейнера). Pipeline: ≈ 50 минут (последовательные ручные прогоны двух источников). Pipeline-простой не влияет на API; оба независимы.

7.4 Cron включается отдельным task'ом

ET-009 не активирует автоматический cron. После двух успешных ручных прогонов подряд DevOps вручную раскомментирует cron-записи из ET-008 (/etc/cron.d/enduro-gps).

7.5 Rollback

Сценарий Действие Время
Откат конфигов (вернуть enabled: false) git revert <commit> + docker compose up -d --no-deps app ≈ 2 мин
Откат БД (если новые источники запортили данные) cp backups/gps_tracks-<date>.sqlite data/gps_tracks.sqlite + рестарт API ≈ 1 мин
Точечное удаление источника без отката кода Открыть config/gps_sources.yaml на mva154, выставить enabled: false, рестарт API (cache-clear) ≈ 1 мин
Удаление треков конкретного источника DELETE FROM tracks WHERE sources_json LIKE '%<id>%' (через ssh + sqlite3) ≈ 1 мин

8. Cron / scheduled jobs

Нет в ET-009. Cron активируется отдельным DevOps-task'ом после ETC-009 (см. §7.4).

9. Ресурсы (CPU / RAM / диск)

9.1 API-контейнер

Никаких изменений. Дополнительные source-ID не нагружают endpoint (только новые значения в properties.sources).

9.2 gps-collector контейнер (во время прогона)

Метрика EnduroRussia Wikiloc OSM (для сравнения)
CPU (peak) < 5% от 1 vCPU < 5% от 1 vCPU < 10%
RAM (peak) ≤ 150 МБ ≤ 150 МБ ≤ 200 МБ
Network egress ≈ 30 МБ ≈ 5 МБ ≈ 100 МБ
Длительность 2030 мин 1025 мин 13 часа (ЦФО)
Disk write rate низкий (≤ 1 МБ/мин) низкий средний

Все три параллельно gps-collector cgroup-limit'ы (cpus: 1.0, mem_limit: 512m) — никаких изменений по сравнению с ET-008.

9.3 Диск

Прирост data/gps_tracks.sqlite после первого прогона ET-009: +2050 МБ. Снимок backup того же объёма. Не влияет на disk budget.

10. Наблюдаемость

Артефакт Состояние после ET-009
GET /api/gps-tracks/health Возвращает tracks_by_source = {osm, enduro_russia, wikiloc} после первых прогонов
/var/log/enduro-trails/gps-collect.log Логи ручных прогонов (через >> ... 2>&1 при ssh)
pipeline_runs в БД Новые записи для source_id ∈ {enduro_russia, wikiloc}
Docker docker compose logs app Без изменений

10.1 Алерты

Нет новых алертов. Существующие правила ET-008 (cron MAILTO, db_size_mb > 2 ГБ) применяются как есть.

Опционально (out of scope ET-009): добавить ручную проверку /api/gps-tracks/health в еженедельный operations-review для двух новых источников.

10.2 Logrotate

Без изменений.

11. Безопасность

Никаких изменений по security-модели по сравнению с ET-008:

  • XML-парсинг GPX через defusedxml.ElementTree;
  • скрейпинг — только outgoing;
  • cache-clear endpoint остаётся docker-internal через nginx allow/deny.

11.1 Новые atack-vectors

Vector Митигация
Wikiloc возвращает malformed HTML с XSS-payload Парсер использует regex, не интерпретирует HTML как DOM. JS не исполняется на сервере. Любой malformed HTML — 0 треков без падения
EnduroRussia API возвращает malformed JSON httpx.Response.json() бросает exception → graceful return из generator
Wikiloc / EnduroRussia возвращают XML-bomb в GPX defusedxml блокирует billion-laughs (наследуется из ET-008)
Поддельный 403 от Wikiloc → DoS pipeline Graceful-stop ≠ ошибка; следующий прогон попробует снова. Cron-окно (3 дня) > recovery-окна (часы)

12. Влияние на C4 / архитектурную документацию

Изменения для отражения в docs/architecture/README.md:

  • Таблица «Внешние источники pipeline» (lines 53-58 в текущем README):
    • EnduroRussia.ru: ADR-010 (proposed/blocked)ADR-010 (accepted);
    • добавить строку Wikiloc | HTML + GPX | proprietary (некоммерческое использование) | ADR-012 (accepted) | да;
    • ttrails.ru: без изменений.

Изменения для отражения в docs/architecture/adr/README.md:

  • ADR-010: status updated to accepted;
  • ADR-012: новая строка таблицы;
  • ADR-013: новая строка таблицы (с ссылкой на ET-009).

C4 mmd-диаграмм в проекте нет (ET-008 §12 явно зафиксировано). ET-009 не создаёт диаграмм — изменение «активация existing source» выражается в текстовом README.

13. Вывод

ET-009 — minimal-change на инфра-уровне:

  • 0 новых сервисов / 0 новых БД / 0 новых cron / 0 новых env / 0 новых портов;
  • Все изменения локализованы в config/*.yaml, src/web/style*.json, тестовых фикстурах и src/api/gps_tracks/sources/wikiloc.py (8 строк для max_tracks_per_run);
  • Деплой = git pull + рестарт API + один ручной прогон;
  • Rollback = git revert или ssh-правка enabled: false.

Эскалация: не требуется (arch:major-change не выставлен, ADR-013 §«Классификация»).