21 KiB
type, work_item_id, title, version, status, created_at, authors
| type | work_item_id | title | version | status | created_at | authors | |
|---|---|---|---|---|---|---|---|
| data-requirements | ET-012 | Требования к данным — ET-012: Снижение minzoom публичных треков до z5 | 1 | approved | 2026-06-04 |
|
Требования к данным — ET-012
1. Резюме
ET-012 — pure read pattern change. Никаких изменений схемы БД, никаких новых таблиц, индексов, миграций, файлов БД, ключей localStorage, изменений конфигов источников.
Меняется только как существующие данные читаются и
сериализуются в MVT при z ∈ {5, 6}:
build_gps_mvtотбирает другой наборrows(фильтр поlength_m) и применяет более жёсткий лимит фич;_simplify_coordsприменяет другойtoleranceDouglas-Peucker'а к существующим WKB-координатам.
Меняется:
- набор фич, попадающих в MVT-тайл при
z ∈ {5, 6}; - размер итогового protobuf MVT (за счёт меньшего числа фич и более агрессивного упрощения).
Не меняется:
- schema таблицы
tracks(ET-008 / ADR-005); - schema таблицы
pipeline_runs; - индексы
idx_tracks_geom(R-tree),min_lon/max_lon/min_lat/max_lat; - контракт API
/api/gps-tracks/*(REQ-F-15); - содержимое отдельных треков (geom, name, sources_json, etc.);
- dedup-алгоритм (
compute_dedup_key); - ACTIVITY_TYPES enum;
- маппинги
SOURCE_ATTRIBUTIONS,SOURCE_LABELS; - localStorage ключи и значения клиента (REQ-F-18);
- содержимое
config/gps_sources.yaml,config/gps_regions.yaml(REQ-F-16).
2. Архитектурные границы данных
| Слой данных | Тип | Расположение | Изменения в ET-012 |
|---|---|---|---|
OSM-vector (trails) |
существующий | /app/data/centralfederal.sqlite |
нет |
| Личные GPX треки (ET-006) | существующий | браузер (memory) | нет |
| Публичные GPS треки (ET-008) | существующий | /app/data/gps_tracks.sqlite |
read-only: новые комбинации параметров (z, x, y) теперь принимаются (z=5/6/7); никаких INSERT/UPDATE/DELETE |
| OSRM-граф | существующий | /app/data/enduro.osrm.* |
нет |
| User UI state | существующий | localStorage |
нет новых ключей, нет миграции |
MVT-кэш в RAM app |
существующий | _gps_tile_cache (Python dict) |
расширяется ключевым пространством: теперь могут лежать тайлы с z ∈ {5,6,7} в дополнение к 8..11. Ёмкость 1024 — без изменений |
| Серверный MVT-тайл (выход) | существующий формат, новый z | bytes в HTTP response | формат application/x-protobuf (Mapbox Vector Tile spec), source-layer gps_tracks, properties как в ET-008 (id, activity, source, sources, length_km, name, ext_url) |
| Клиентский MapLibre LRU | существующий | браузер | расширяется ключевым пространством аналогично серверу |
3. Серверные данные — gps_tracks.sqlite
3.1 Schema
Без изменений vs ET-008/ET-009/ET-011. См.
docs/work-items/ET-008/08-data-requirements.md §3.1, §3.5. Никаких
ALTER TABLE / DROP COLUMN / CREATE INDEX.
3.2 Используемые поля в SELECT при сборке MVT z5-z7
| Поле | Использование |
|---|---|
id |
MVT property |
name |
MVT property |
activity_type |
MVT property |
length_m |
NEW USE: фильтр length_m >= min_length_m где min_length_m=10000 (z5) или 5000 (z6) или 2000 (z7). Раньше фильтр применялся только для z≤7 с порогом 2000 |
points_count |
не используется в MVT (только в /download, ET-011) |
geom (WKB) |
парсится через _wkb_to_coords() → [(lon, lat), ...] → передаётся в _simplify_coords(coords, z). NEW: для z=5 tolerance=0.04°, для z=6 tolerance=0.018° |
sources_json |
первый элемент → MVT property source; весь список → comma-separated в property sources |
external_urls_json |
первый URL → MVT property ext_url |
dedup_key, description, tags_json, user, inserted_at, updated_at, created_at, min_lon..max_lat |
не используется в MVT (часть полей нужна только в /download или GeoJSON-режиме z≥12) |
Запрос идентичен ET-008 (get_tracks_in_bbox):
SELECT t.* FROM tracks t WHERE t.ROWID IN (
SELECT pkid FROM idx_tracks_geom WHERE
xmin <= ? AND xmax >= ? AND ymin <= ? AND ymax >= ?
) ORDER BY length_m DESC
Изменения SQL: нет. Фильтр по length_m — на Python-стороне в
build_gps_mvt, чтобы не вводить новые SQL-параметры (TRZ §3 REQ-F-08).
3.3 Объёмы данных
| Метрика | Текущее (ET-009) | Прогноз через 12 мес. | Гейт ET-012 |
|---|---|---|---|
Число треков в gps_tracks.sqlite |
~500 (test) | ~5000 | M-6 (p95 build_gps_mvt z5 ≤ 500 мс на БД 5000) |
| Длинных треков (≥ 10 км) | ~150-200 (ЦФО) | ~1500-2000 | M-8 (размер MVT z5 ≤ 200 KB) |
| Точек на трек (среднее) | 2000-5000 | 2000-5000 | (Tolerance Douglas-Peucker отсечёт лишнее) |
| Размер БД (на диске) | ~50 MB | ~500 MB | Disk-impact на mva154 — пренебрежимо |
При БД из 5000 треков и БД-индекс по bbox:
- Один z=5 тайл накрывает ~1250×1250 км по экватору, ~700×1250 на 55° с.ш.
- В bbox z=5 над ЦФО попадает ≤ 100% длинных треков ЦФО = ~1500.
- После Python-фильтра
length_m ≥ 10000остаётся ~1500 длинных треков → ограничиваетсяlimit=1500. - После
_simplify_coords(tolerance 0.04° → ~5-30 точек на трек) → средний размер фичи ≈ 200 байт → MVT ≈ 300 KB до gzip → ≈ 80 KB после.
3.4 Индексы
Без изменений vs ET-008. Существующий R-tree-индекс
idx_tracks_geom достаточен для bbox-запросов z=5. Вторичный индекс
на length_m не нужен — ORDER BY length_m DESC дёшев на
выборках < 5000 строк (Python sort после SQL-фильтра по bbox; SQLite
делает табличный SCAN после R-tree фильтра).
Watch-flag (TRZ §6, R-4): если PERF-Z5-01 покажет деградацию при
росте БД > 20k треков — рассмотреть CREATE INDEX idx_tracks_length ON tracks(length_m DESC) как отдельный work-item. Не в MVP.
4. Клиентские данные
4.1 localStorage
Без изменений vs ET-008/ET-009/ET-011. Используются ключи:
| Ключ | Назначение | Изменения в ET-012 |
|---|---|---|
gps-tracks-enabled |
bool — чекбокс «Публичные треки» | нет |
gps-tracks-activities |
JSON-array — выбранные активности | нет |
gps-tracks-sources |
JSON-array — выбранные источники | нет |
gps-tracks-color-mode |
`"source" | "activity"` |
REQ-F-18 в TRZ §3: «никакой миграции localStorage не нужно».
Существующие сессии при следующей загрузке автоматически получают
новый порог GPS_TRACKS_MIN_ZOOM = 5 и видят слой на z5-z7.
4.2 MapLibre LRU (browser-side)
Браузерный MapLibre кэширует тайлы в собственном LRU. После ET-012:
- Ключевое пространство кэша:
(source_id, z, x, y)— расширяется наz ∈ {5, 6, 7}. - Объём — управляется MapLibre, по умолчанию ~100 МБ; пользовательский опыт не страдает.
- Никакой синхронизации с серверным
_gps_tile_cacheне нужно (independent caches; их инвалидация — черезPOST /api/gps-tracks/cache/clear, которая инвалидирует только серверный LRU; клиент дёрнет свежий MVT при следующем reload или после move-выхода-возврата за пределы LRU).
5. Контракты API
5.1 GET /api/gps-tracks/tiles/{z}/{x}/{y}.mvt
| Аспект | До ET-012 | После ET-012 |
|---|---|---|
Path-параметр z |
принимается 0 ≤ z ≤ 22 |
принимается 0 ≤ z ≤ 22 (без изменений) |
| Response 200 | для z=8..11 — непустой MVT; для z<8 — пустой MVT | для z=5..11 — непустой MVT (новые z=5/6/7); для z<5 — пустой MVT |
| Response Content-Type | application/x-protobuf |
application/x-protobuf (без изменений) |
| Properties фич | id, activity, source, sources, length_km, name, ext_url |
без изменений |
| Cache-Control | public, max-age=300 |
без изменений |
| Размер тела (z5) | (раньше не использовалось клиентом, был ~0-50 KB пустой) | ≤ 200 KB до gzip (M-8) |
Старые клиенты (старый gps_tracks.js, который никогда не
запрашивал z=5..7) — продолжают работать. Никакого breaking change
в контракте нет.
5.2 GET /api/gps-tracks?bbox=...
Без изменений. Этот endpoint обслуживает GeoJSON-режим z≥12, а ET-012 не трогает z≥12.
5.3 POST /api/gps-tracks/cache/clear
Без изменений. Инвалидирует серверный _gps_tile_cache целиком
(все z). Pipeline gps-collector дёргает его после успешного прогона
(ADR-007 §7). После ET-012 этот вызов очищает и тайлы z=5..7
автоматически.
5.4 GET /api/gps-tracks/{id}/download
Без изменений. ET-011 endpoint, не зависит от zoom.
5.5 GET /api/gps-tracks/health
Без изменений. Возвращает tracks_total, tracks_by_source,
last_pipeline_run.
6. Миграции
Нет. Никаких миграций БД, никаких миграций localStorage, никаких миграций конфигов.
При деплое в test:
- БД
data/gps_tracks.sqlite— без изменений (read-only дляapp). data/centralfederal.sqlite— без изменений (другой слой).- Серверный MVT-кэш — очищается через
POST /api/gps-tracks/cache/clearдля подстраховки (см.07-infra-requirements.md§6.2 шаг 4); это не миграция, а кэш-инвалидация. - Клиентский MapLibre LRU — самоочищается при reload браузера; явной миграции не нужно.
7. Тестовые данные
7.1 Для unit-тестов
tests/unit/test_gps_mvt_zoom_tiers.py (новый, REQ-F-09):
- Использует in-memory SQLite (как существующие тесты в
tests/unit/test_gps_mvt.py). - Фикстуры: треки разной длины (например, 1 км, 3 км, 6 км, 12 км, 25 км), геометрия — простые LineString из 5-10 точек.
- Никаких внешних зависимостей.
tests/unit/test_gps_mvt_simplify.py (новый или расширение, REQ-F-10):
- Чистые unit-тесты
_simplify_coords(coords, z)— массивы coords захардкожены, БД не нужна.
7.2 Для integration-тестов
tests/integration/test_gps_tile_z5_z7.py (новый, REQ-F-11):
- Использует existing fixture
gps_tracks_test_db(фикстура изconftest.pyET-008), которая заливает 50 треков по ЦФО разной длины с реалистичными координатами. - При необходимости расширяется до 200 треков для IT-Z5-02.
7.3 Для performance-теста
tests/performance/test_gps_mvt_z5_perf.py (новый, REQ-F-13):
- Fixture: 500 треков по ЦФО, каждый ≥ 10 км, реалистичная геометрия.
- Маркер
@pytest.mark.perf— не запускается в основномmake test. - Запускается вручную или отдельным CI-джобом.
7.4 Для UI-тестов
tests/e2e/test_ui_gps_z5.spec.ts (новый, REQ-F-14 / 04b-ui-test-cases.md):
- Запускается на test-среде
https://openclaw.mva154.duckdns.org/enduro/. - Данные — реальная БД test-среды (после ET-009 — ~200 треков ЦФО).
- Скриншот-эталоны для AC-08 (визуальная читаемость) — в
tests/e2e/screenshots/et012/.
8. Резервные копии и DR
Без изменений vs ET-008. БД gps_tracks.sqlite бэкапится тем же
crontab-скриптом, что и раньше. RPO = 0 (ET-012 не трогает данные).
9. Privacy / Compliance
| Аспект | Требование |
|---|---|
| PII в новых MVT | Нет нового PII. На z=5..7 в MVT-фичу попадают те же поля, что и на z=8..11: id, activity, source, sources, length_km, name, ext_url. Поле user (потенциальный PII) в MVT не попадает на любых z. Поле name может содержать имя автора — но это уже было разрешено ET-008/ADR-005 для всех z ≥ 8. |
| Licensing | Без изменений (ADR-009 OSM ODbL, ADR-010 EnduroRussia accepted, ADR-012 Wikiloc accepted с обезличиванием). Снижение minzoom не меняет, какие источники exposed клиенту — все треки в БД уже прошли licensing-guard pipeline'а |
| Attribution | MapLibre attribution control отображает атрибуцию всех активных источников; это работает независимо от zoom — на z=5 пользователь видит те же бейджи «© OSM |
10. Связанные документы
01-brd.md§6 Зависимости.Backend, §6 Зависимости.Тесты02-trz.md§3 REQ-F-09..F-14 (тесты), REQ-F-16..F-18 (не меняем конфиги/стили/localStorage)06-adr/ADR-016-z5-tiling-policy.md§«Решение», §«Последствия»07-infra-requirements.md§4 (LRU, RAM), §6 (cache clear at deploy)10-tech-risks.md(этот пакет)docs/work-items/ET-008/08-data-requirements.md§3 (schema, индексы) — наследиеdocs/work-items/ET-009/08-data-requirements.md(если есть) — наследие