23 KiB
23 KiB
type, work_item_id, title, version, status, created_at, authors
| type | work_item_id | title | version | status | created_at | authors | |
|---|---|---|---|---|---|---|---|
| tech-risks | ET-012 | Технические риски — ET-012: Снижение minzoom публичных треков до z5 | 1 | approved | 2026-06-04 |
|
Технические риски — ET-012
Технические риски этапа снижения нижнего порога видимости слоя публичных GPS-треков с z=8 до z=5. Бизнес-риски — в BRD §5 (R-1..R-10). Шкала: вероятность (Н/С/В) × влияние (Н/С/В).
R-T-1 — Размер MVT-тайла z=5 > 200 KB на реальных данных
- Описание: На густонаселённых регионах (Москва, Урал) при росте
БД до 5000+ треков фильтр
length_m ≥ 10000+limit=1500может не сработать как страховка: 1500 треков × 200 байт после упрощения = ~300 KB до gzip, что близко к гейту M-8 (200 KB декомпрессировано на клиенте). - Вероятность / Влияние: С / С.
- Митигация:
- Архитектурное решение (ADR-016 §T-2): выбраны намеренно
консервативные параметры (
min_length 10 км,limit 1500) — это компромисс, а не «впритык». Запас 30-50% по M-8 при текущей БД (~500 треков ЦФО). - Хук на снижение: если PERF-Z5-01 или AC-10 покажут размер
200 KB — снизить
limitдо 1000 вbuild_gps_mvt. Это правка одной константы, не требует архитектурного re-decide (см. ADR-016 §«Технический долг»). - Тесты: IT-Z5-01, IT-Z5-02 (REQ-F-11) — гейтируют размер на 50-200 треков; ручная проверка AC-10 — на реальной БД test-среды после деплоя.
- Архитектурное решение (ADR-016 §T-2): выбраны намеренно
консервативные параметры (
R-T-2 — DP-tolerance 4 км на z5 «убивает» геометрию треков 10-15 км
- Описание: Трек длиной 12 км с реальной траекторией (зигзаги лесных дорог) после Douglas-Peucker с tolerance 0.04° (~2.6 км по долготе на 55° с.ш.) превращается в 2-3 точки → визуально «прямая линия от А до Б». Пользователь думает, что трек прямой, и недооценивает сложность.
- Вероятность / Влияние: В / Н.
- Митигация:
- Архитектурное решение (ADR-016 §T): на z5 трек ≤ 5 км схлопывается в прямую — это спецификация, не баг (BRD §5 R-2). На z5 пиксель ≈ 5 км, поэтому даже идеально точный зигзаг не видно глазом.
- Спецификация поведения для пользователя: «z5 — общий обзор сети; для деталей зумьте до z=10+». Это документировано в BRD §2.2 и TRZ §6.
- Тест: TC-UI-12-Z5-Q (качественный) — оператор глазами проверяет, что на z5 видны минимум 3 разных «нити» в кадре (AC-08).
R-T-3 — Линия 0.5 px на z5 невидима на 1×-DPR мониторе
- Описание: Если бы оставили
interpolate [..., 8, 1.0, ...], на z=5 MapLibre сэмплирует значение слева от первого стопа = 1.0, но после anti-aliasing на 1× мониторе линия «съедается» до ≤ 0.5px. - Вероятность / Влияние: С (без митигации — В) / Н.
- Митигация:
- Архитектурное решение (ADR-016 §L-B / REQ-F-05): явный стоп
5, 0.8в_gpsLayerDef.paint['line-width']. 0.8 CSS-px = 1 физ.px на 1×-мониторе после округления GPU. Стоп5, 1.8в_gpsHaloDef(соотношение ~2.25×) — ореол не «съедает» линию. - Тесты: TC-UI-01-Z5 (Playwright), TC-UI-10-Z5-MOBILE (mobile viewport) — гейтируют видимость линии.
- Архитектурное решение (ADR-016 §L-B / REQ-F-05): явный стоп
R-T-4 — bbox-запрос на z5 тянет всю БД (R-tree fallback to full scan)
- Описание: Один z=5 тайл накрывает ~1250×1250 км по экватору, ~700×1250 на 55° с.ш. При БД 5000 треков по ЦФО — все 5000 строк имеют bbox внутри тайла, R-tree-индекс возвращает все ROWID, и далее SQLite делает SCAN по 5000 строк для подгрузки полей. На CI-runner это ≤ 100 мс, на mva154 — оценочно ≤ 150 мс (HDD-storage).
- Вероятность / Влияние: С / Н.
- Митигация:
- Архитектурное решение (ADR-016 §B): buffer 10% bbox не
меняем в MVP — лишний 10%-запас погоды не делает при том, что
основной фильтр — Python-фильтр по
length_mпосле SELECT. - PERF-Z5-01 (REQ-F-13) — гейт; при росте БД и деградации —
добавляем индекс на
length_m DESCотдельным минорным патчем (см. ADR-016 §«Технический долг»). - Метрика M-6/M-7 — наблюдаем p95 в
uvicorn.accessпосле деплоя (см.07-infra-requirements.md§7.1).
- Архитектурное решение (ADR-016 §B): buffer 10% bbox не
меняем в MVP — лишний 10%-запас погоды не делает при том, что
основной фильтр — Python-фильтр по
R-T-5 — LRU 1024 переполняется при walk-through-world
- Описание: Если пользователь панорамирует карту на z=5 по всему
миру, видит ~1024 уникальных тайла (z5 = 32×32). Серверный
_gps_tile_cacheёмкостью 1024 при FIFO-вытеснении начинает выкидывать ранее запрошенные → повторный pan дёргает cold-build снова. - Вероятность / Влияние: Н / Н.
- Митигация:
- Архитектурное решение (ADR-016 §C): размер LRU 1024 не меняем в MVP. На практике пользователь работает с регионом (ЦФО + соседние области = ~20-30 тайлов z5).
- Метрика M-11 — гейт; если cache hit ratio < 80% — поднимаем до 2048 отдельным патчем.
- Альтернатива (отложена): pre-render z=5 grid на диск при деплое (ADR-016 §P-B отклонён в MVP, но открыт для отдельного work-item).
R-T-6 — Hint «Зум 8+» забыт в HTML → пользователь видит линии и подсказку «увеличь зум»
- Описание: В
src/web/index.htmlстрока<span ... id="public-tracks-zoom-hint">Зум 8+</span>. Если в ходе реализации правка REQ-F-07 потеряется (например, мердж-конфликт), у пользователя на z<5 будет hint «Зум 8+», который противоречит фактическому порогу 5. - Вероятность / Влияние: С / Н.
- Митигация:
- Архитектурное решение (REQ-F-07): в HTML текст явно меняется
на «Зум 5+». Логика показа в
_syncGpsLayersVisibilityавтоматически используетGPS_TRACKS_MIN_ZOOM— порог переезжает автоматически. - Тесты: AC-05 (текст «Зум 5+»), TC-UI-04-HINT-OFF / TC-UI-05-HINT-ON (Playwright).
- Acceptance check в
02-trz.mdREQ-F-01grep— гарантирует, что других вхождений константы со старым значением нет.
- Архитектурное решение (REQ-F-07): в HTML текст явно меняется
на «Зум 5+». Логика показа в
R-T-7 — Halo на спутнике на z5 «глушит» подложку
- Описание: Если halo-line-width на z5 окажется слишком большим
(например, по ошибке остался стоп
5, 4.0), белый ореол на спутниковой подложке закрывает большую часть рельефа в кадре. - Вероятность / Влияние: Н / Н.
- Митигация:
- Архитектурное решение (REQ-F-06 / ADR-016 §L-B): halo z5
= 1.8 CSS-px; ограничено F-10 BRD
≤ 2 px. Соотношение к line-width (1.8 / 0.8 ≈ 2.25) — стандартное для трэйл-линий. - Тесты: TC-UI-11-Z5-SAT (Playwright со спутниковой подложкой); AC-17 (halo-width ≤ 2 px, halo не «глушит» подложку).
- Архитектурное решение (REQ-F-06 / ADR-016 §L-B): halo z5
= 1.8 CSS-px; ограничено F-10 BRD
R-T-8 — Регрессия на z=8..11 из-за разделения tier z≤7 на z≤5/z=6/z=7
- Описание: В новой tier-таблице (ADR-016 §«Решение» п.2) ранее
единый блок
z ≤ 7 → min_length=2000, limit=3000разбит наz≤5: min_length=10000, limit=1500 | z=6: min_length=5000, limit=2000 | z=7: min_length=2000, limit=3000. Регрессия может проявиться, если при разбиении нечаянно поломан z=7 (например, ошибочныйelif z <= 7вместоelif z == 7). - Вероятность / Влияние: С / С.
- Митигация:
- Архитектурное решение (REQ-F-03): код-сниппет в TRZ §3.3
точно указывает структуру
if z <= 5 / elif z == 6 / elif z == 7 / elif z <= 9 / .... - Регрессионные тесты: UT-Z7-01, UT-Z8-01, UT-Z12-01 (REQ-F-09), IT-REGRESS-Z8-01, IT-REGRESS-Z10-01 (REQ-F-12), AC-06.
- Code review проверяет if-elif-цепочку построчно.
- Архитектурное решение (REQ-F-03): код-сниппет в TRZ §3.3
точно указывает структуру
R-T-9 — Cache poisoning: после deploy старые тайлы z8-z11 остались с прежней tier-логикой
- Описание:
_gps_tile_cache— in-memory FIFO; при перезапускеappон очищается автоматически. Но если операторdocker compose restart appне сделал, а толькоdocker compose up -d --no-deps appпересобрал образ → новый процесс стартует с пустым кэшем, всё ок. Риск только при использованииdocker compose execили hot-reload (не наш случай в проде). - Вероятность / Влияние: Н / Н.
- Митигация:
- Архитектурное решение:
docker compose up -d --no-deps appв07-infra-requirements.md§6.2 шаг 2 — пересоздаёт контейнер, кэш пустой. - Подстраховка:
POST /api/gps-tracks/cache/clearв шаге 4 (на случай race conditions). - Браузерный кэш: MapLibre LRU при reload очищается;
Cache-Control: max-age=300ограничивает максимум 5 минут «застрявших» тайлов в браузерном кэше.
- Архитектурное решение:
R-T-10 — _simplify_coords падает с ValueError при пустом coords на z=5
- Описание: Существующий код:
if len(coords) < 3: return coords— защита от пустых/коротких массивов. После добавления tier для z5 проверка остаётся. Но:shapely.LineString(coords).simplify(0.04, ...)при tolerance ≥ длины трека вернёт LineString из 2 точек (концы) или пустую коллекцию. Если результат пустой — fallbackreturn coordsвозвращает оригинал. - Вероятность / Влияние: Н / Н.
- Митигация:
- Архитектурное решение: существующий fallback
return result if len(result) >= 2 else coords(mvt.py:50) остаётся. Покрытие тестом UT-SIMP-Z5-02 (зигзаг 100 точек → 2 точки = валидный LineString). - Дополнительный тест (рекомендуется в pull request):
_simplify_coords([(37.0, 55.0), (37.001, 55.001)], 5)→ возвращает оригинал (2 точки).
- Архитектурное решение: существующий fallback
R-T-11 — Размер MVT z=5 = 0 байт на регионе без длинных треков
- Описание: После фильтра
length_m ≥ 10000в регионах с только короткими треками (например, лесопарки внутри города) тайл z=5 содержит 0 фич → возвращаетсяb""._row_to_geojson_feature/build_gps_mvtвозвращают пустой protobuf, что MapLibre корректно интерпретирует как «фич нет». - Вероятность / Влияние: С / Н (это ожидаемое поведение).
- Митигация:
- Архитектурное решение: на z=5 в регионе без длинных треков — пусто. Это специфицировано в BRD §2.2 и AC-03 (требуется БД с ≥ 50 треков ≥ 10 км по ЦФО).
- Тест: IT-Z5-03 (REQ-F-11) — тайл z=5 за пределами региона возвращает 200 с пустым телом.
- UX: пользователь видит «пустую карту» на z=5, но hint не показывается (zoom ≥ 5); если пользователь зумит до z=8, появляются короткие треки. Естественная семантика.
R-T-12 — Старый клиент (закэшированный в браузере) делает запросы только на z≥8
- Описание: Пользователь с открытой вкладкой неделю назад имеет
закэшированный
gps_tracks.jsсо старымGPS_TRACKS_MIN_ZOOM = 8. После деплоя при reloadgps_tracks.jsобновится (если есть?v=...versioning) или дотянется service-worker'ом. Service worker — не настроен в MVP (PH-9 не реализована). - Вероятность / Влияние: С / Н.
- Митигация:
- Архитектурное решение:
src/web/index.htmlзагружаетgps_tracks.jsнапрямую (без SW). При reload браузер дёрнет последнюю версию (если nginx отдаёт нужные cache-headers). Если нет — пользователь сделаетCtrl+F5после очередного апа. - Backwards compat: старый клиент с
MIN_ZOOM=8продолжает работать; он просто не запрашивает z=5..7. Никаких 4xx-ответов нет (REQ-F-15 — контракт не сломан). - Митигация в долгую: PWA / SW (PH-9, отдельный work-item) введёт правильную inval-стратегию.
- Архитектурное решение:
R-T-13 — DDoS на новый z=5 endpoint (бот ходит по 32×32 z5 grid)
- Описание: Поскольку endpoint без auth и без rate-limit, скрипт-крулер может запросить все 1024 тайла z=5 за минуту → 1024 × ~200 мс build = ~3.5 минуты CPU на сервере. Не убийственно, но заметно.
- Вероятность / Влияние: Н / Н.
- Митигация:
- Архитектурное решение: rate-limit не вводим в MVP (см.
07-infra-requirements.md§3.2). LRU кэш съест второй проход — cold пройдёт один раз. - Мониторинг: в первую неделю после деплоя оператор смотрит
nginx access.logна аномалии (см.07-infra-requirements.md§7.1). - Эскалация: если обнаружится паттерн —
slowapi-middleware (отдельный DevOps-task).
- Архитектурное решение: rate-limit не вводим в MVP (см.
R-T-14 — Конфликт с halo при переключении spectator/satellite на z5
- Описание: При переключении подложки
applyBaseLayer()(ET-007) должен корректно показать/скрыть halo для GPS-треков. На z=5 halo активен (zoom ≥ GPS_TRACKS_MIN_ZOOM AND zoom < GPS_TRACKS_ZOOM_CUTOFF AND base === 'satellite'). Если вapplyGpsHaloVisibilityесть hardcoded порог z≥8 — будет расхождение. - Вероятность / Влияние: Н / Н.
- Митигация:
- Архитектурное решение: в
gps_tracks.jsсуществующая логика_syncGpsLayersVisibility/applyGpsHaloVisibilityиспользуетGPS_TRACKS_MIN_ZOOMкак константу — порог переезжает автоматически (verified bygrepв TRZ §3 REQ-F-01). - Тесты: TC-UI-11-Z5-SAT (Playwright со спутниковой подложкой), AC-17.
- Архитектурное решение: в
R-T-15 — Performance тест PERF-Z5-01 нестабилен на CI
- Описание: PERF-Z5-01 (REQ-F-13) измеряет p95 build_gps_mvt z=5 при 500 треках. CI-runner может иметь cold I/O в первом прогоне → fail. Это flaky-тест.
- Вероятность / Влияние: С / Н.
- Митигация:
- Архитектурное решение: PERF-тест с маркером
@pytest.mark.perfзапускается отдельным джобом (TRZ §3.13) — не блокирует merge. Логируется в13-test-report.mdдля тренд-анализа. - Дизайн теста: делать 10 повторов, отбрасывать первый (warmup) — стандартный паттерн для micro-benchmark'ов.
- Gate: avg ≤ 200 мс, p95 ≤ 500 мс (gentle).
- Архитектурное решение: PERF-тест с маркером
R-T-16 — Конфигурация nginx gzip для application/x-protobuf пропала
- Описание: Если nginx config был перезатёрт (например, после
переустановки) и
application/x-protobufне вgzip_types, размер MVT z5 пойдёт unzipped (~80 KB на тайл) → мобильный трафик и latency растут. - Вероятность / Влияние: Н / С.
- Митигация:
- Smoke-проверка в
07-infra-requirements.md§6.2 шаг 3:curl -Iсмотрит наcontent-encoding: gzipпосле деплоя. - Если gzip нет — операт восстанавливает nginx config из git
(
infra/nginx/openclaw.confили эквивалент).
- Smoke-проверка в
Сводная таблица
| # | Риск | Вер | Влиян | Митигация (тип) |
|---|---|---|---|---|
| R-T-1 | Размер MVT z5 > 200 KB | С | С | Архитектурное (tier T-2) + гейт-тест |
| R-T-2 | DP-tolerance ломает геометрию коротких треков | В | Н | Спецификация (z5 = обзор) |
| R-T-3 | Линия невидима на 1×-DPR | С | Н | Архитектурное (line-width стоп 0.8) |
| R-T-4 | bbox-запрос z5 тянет всю БД | С | Н | Гейт-метрика + index-watch flag |
| R-T-5 | LRU 1024 переполнение | Н | Н | Метрика M-11; capacity hook |
| R-T-6 | Hint «Зум 8+» забыт | С | Н | grep-проверка + UI-тест |
| R-T-7 | Halo «глушит» подложку | Н | Н | Архитектурное (1.8 px) + UI-тест |
| R-T-8 | Регрессия z8-z11 из-за tier-rewrite | С | С | Снимок tier в TRZ + регресс-тесты |
| R-T-9 | Cache poisoning после deploy | Н | Н | Procedure (cache clear) в infra |
| R-T-10 | _simplify_coords падает на пустых |
Н | Н | Existing fallback + unit-тест |
| R-T-11 | Пустой MVT в регионе без длинных треков | С | Н | Specified behavior + IT-Z5-03 |
| R-T-12 | Старый клиент в кэше браузера | С | Н | Backwards-compat (контракт) |
| R-T-13 | DDoS на новый z=5 endpoint | Н | Н | LRU защищает; rate-limit отложен |
| R-T-14 | Halo не sync на z5 | Н | Н | Existing-pattern reuse + UI-тест |
| R-T-15 | PERF-тест flaky на CI | С | Н | Marker @perf, отдельный джоб |
| R-T-16 | nginx gzip пропал | Н | С | Smoke-проверка после деплоя |
Связанные документы
01-brd.md§5 Бизнес-риски R-1..R-10 (часть пересекается)02-trz.md§3 REQ-F-09..F-14 (тесты), §4 NFR06-adr/ADR-016-z5-tiling-policy.md§«Решение», §«Последствия»07-infra-requirements.md§3 (rate-limit), §6 (procedure), §7 (мониторинг)08-data-requirements.md§3.4 (индексы), §5 (контракты)