---
type: adr
work_item_id: ET-006
adr_id: ADR-003
title: "Парсинг GPX — DOMParser в основном потоке с чанковой конвертацией"
status: accepted
date: 2026-05-22
authors:
  - "agent:architect"
supersedes: null
superseded_by: null
---

# ADR-003: Парсинг GPX — `DOMParser` в основном потоке с чанковой конвертацией

## Контекст

- ТЗ REQ-F-02 **предписывает** использовать `DOMParser` (XML → DOM → GeoJSON).
- ТЗ NF-01: парсинг файла 50 МБ ≤ 5 с на устройстве с 4 ГБ RAM; во время
  парсинга показывать индикатор загрузки; рендеринг 500K точек без видимых
  фризов при pan/zoom.
- BRD (таблица рисков) упоминает Web Worker как **возможную** митигацию
  («при необходимости — Web Worker для парсинга») — не как требование.

Ключевое техническое ограничение, определяющее решение:

> **`DOMParser` — это API объекта `Window`. В `WorkerGlobalScope` его нет.**

В выделенном Web Worker нет DOM и нет `DOMParser` — `new DOMParser()` бросит
`ReferenceError`. Следовательно, парсинг в Worker **несовместим** с REQ-F-02:
он потребовал бы либо самописного XML-сканера, либо стороннего XML-парсера.

Это создаёт напряжение между REQ-F-02 (DOMParser) и идеей выноса парсинга
в Worker. Напряжение разрешается данным ADR.

## Решение

1. **Парсинг XML — в основном потоке** через `DOMParser.parseFromString`.

2. **Конвертация DOM → GeoJSON и расчёт статистики — чанками.**
   Это итеративная часть, доминирующая по времени на больших файлах
   (обход 500K+ DOM-узлов, чтение атрибутов, Haversine, дельты высот).
   Обрабатывать порциями (например, по 5–10K точек), между порциями
   отдавать управление event loop (`setTimeout(0)` / `requestAnimationFrame`
   / `requestIdleCallback`). Это сохраняет отзывчивость UI и анимацию
   индикатора загрузки.

3. **Web Worker не используется.**

Атомарный вызов `parseFromString` заблокировать чанками нельзя — он блокирует
основной поток на время своего выполнения. Для реалистичных GPX (< 5 МБ) это
доли секунды; для предельного файла 50 МБ — порядка 1–2 с. Это **принимается**
(см. «Последствия» и риск R-1 в `10-tech-risks.md`).

## Рассмотренные альтернативы

### Альтернатива A: Web Worker + `DOMParser` (отклонена)

Невозможна технически: `DOMParser` отсутствует в `WorkerGlobalScope`.

### Альтернатива B: Web Worker + самописный строковый/regex XML-парсер (отклонена)

- Противоречит REQ-F-02 (предписан `DOMParser`).
- Добавляет в поддержку bespoke-парсер; крайние случаи GPX (namespaces,
  XML-сущности, CDATA, экзотические кодировки) становятся нашей проблемой.

### Альтернатива C: Web Worker + сторонняя XML-библиотека (отклонена)

- Нарушает принцип «минимум зависимостей».
- Требует подключения npm-зависимости / сборщика, которых в проекте нет.

### Альтернатива D: `DOMParser` в основном потоке + синхронная конвертация (отклонена)

- Полная блокировка UI на всё время «парсинг + конвертация» — для больших
  файлов это секунды полного фриза, индикатор загрузки не успевает
  отрисоваться/обновиться.

### Альтернатива E: `DOMParser` в основном потоке + чанковая конвертация (выбрана)

- Ноль новых зависимостей, соответствует REQ-F-02.
- UI отзывчив на доминирующей (итеративной) части стоимости.
- Нет Worker-файла, нет потребности в CSP `worker-src`.

## Последствия

### Положительные

- Соответствие REQ-F-02, ноль новых зависимостей, нет сборщика/Worker-файла.
- CSS-индикатор загрузки анимируется потоком композитора независимо от
  загрузки основного потока — крутится даже во время атомарного парса.
- UI отзывчив во время чанковой конвертации (основная по времени фаза).

### Отрицательные / митигации

| Последствие | Митигация |
|---|---|
| Атомарный `parseFromString` файла 50 МБ блокирует UI на ~1–2 с | Реалистичные GPX-файлы существенно меньше; 50 МБ — потолок валидации, а не норма; индикатор продолжает анимироваться. Зафиксировано как риск R-1. |
| Транзиентный пик памяти на 50 МБ (DOM ~150–300 МБ) | DOM освобождается сразу после конвертации; рекомендуется обнулять ссылку на документ. См. риск R-3. |
| Если Worker когда-либо станет действительно необходим | Потребует замены `DOMParser` → отдельный ADR, superseding данный. |

### Влияние на компоненты

- **Frontend** (`gpx.js`) — реализация парсинга и чанковой конвертации.
- **Backend / API / OSRM / БД** — без изменений (парсинг полностью клиентский).
- **C4-диаграммы** — состав компонентов не меняется → обновление не требуется.

## Связанные

- ТЗ: `docs/work-items/ET-006/02-trz.md` (REQ-F-02, NF-01, §5)
- BRD: `docs/work-items/ET-006/01-brd.md` (§5, риск производительности)
- ADR-002: структура модуля `gpx.js`
- Риски: `docs/work-items/ET-006/10-tech-risks.md` (R-1, R-2, R-3)
