- пометка — одна строка на диапазон (метрика + слой + период), а не провенанс на точку: вопрос диапазонный, а поле у точки стоит того объёма, который устаревание нижнего слоя и приходит экономить - провенанс на точку отвергнут по цене, а не по ненадобности — различие записано, чтобы решение пересмотрели при появлении потребителя - пометку выставляет импорт экспорта, по проверенному прогону; stateOfMind не получает её никогда — его в экспорте Apple нет
71 lines
5.6 KiB
Markdown
71 lines
5.6 KiB
Markdown
# Импорт родного экспорта Apple Health
|
||
|
||
- **Секция:** ядро
|
||
- **Зачем:** Слой sample пуст: полная история и точные сэмплы лежат в zip-архиве и никуда не едут
|
||
- **Теги:** goal:native-export-import
|
||
|
||
Слой `sample` пуст: настоящих сэмплов HealthKit в потоке нет вовсе — HAE отдаёт
|
||
посекундную развёртку, а не измерения (находка 34). Полная история и точные
|
||
сэмплы лежат в zip родного экспорта.
|
||
|
||
Это же основание для устаревания нижнего слоя и единственный способ поднять
|
||
историю глубже недели: дыра старше недели проходами синхронизации не чинится.
|
||
|
||
Формат разобран на девяти экспортах за 5.5 лет (находки 42–45), гадать не
|
||
придётся:
|
||
|
||
- **версии 11 → 13 → 14**, на 14 стоит больше года; за всё время **ни один тип
|
||
записи не исчез**, только добавлялись. Значит незнакомый тип — новый тип, а
|
||
не сломанный парсер: падать на нём нельзя;
|
||
- **`Correlation`** — обёртка из двух записей, ею приезжает давление. Появилась
|
||
только в 2026 году. Парсер по одним `<Record>` разберёт давление как две
|
||
несвязанные метрики и потеряет их парность;
|
||
- **`WorkoutStatistics`** внутри тренировки — с 2024 года;
|
||
- **имя файла локализовано**: `экспорт.xml`, не `export.xml` — так во всех
|
||
девяти архивах;
|
||
- **DTD расходится с данными** (в v11 у `<Me>` на атрибут больше объявленного)
|
||
— валидировать документ его же DTD нельзя;
|
||
- объём: 1.6 ГБ XML и 3.6 млн записей в свежем экспорте — только потоковый
|
||
разбор, документ целиком в память не влезет.
|
||
|
||
Шаги:
|
||
- потоковый разбор `экспорт.xml` в слой `sample`, включая `Correlation`;
|
||
- `HeartRateVariabilityMetadataList` с `InstantaneousBeatsPerMinute` — это
|
||
тот же `heartbeatSeries`, что в HAE (находка 39), 1.25 млн ударов;
|
||
- маршруты GPX и ЭКГ отдельными файлами — их в XML нет;
|
||
- заливка кусками по годам, идемпотентно: повторный импорт того же архива не
|
||
должен ничего менять;
|
||
- `export_cda.xml` игнорируем — это клинический формат тех же данных.
|
||
|
||
## Импорт выставляет пометку покрытия
|
||
|
||
Импорт — единственный, кто знает, какой период каким слоем обеспечен, поэтому
|
||
пометку ставит он, а не отдельный проход задним числом.
|
||
|
||
Форма пометки решена в [lower-layer-expiry](lower-layer-expiry.md): **одна
|
||
строка на диапазон** — `метрика + слой + период + «покрыто проверенным
|
||
экспортом»`. Провенанс на каждую точку не заводим: вопрос диапазонный, а поле у
|
||
точки стоило бы того же объёма, который устаревание нижнего слоя и приходит
|
||
экономить.
|
||
|
||
Два условия, оба из ограничителей той задачи:
|
||
|
||
- пометка ставится **по проверенному** импорту, а не по факту запуска команды.
|
||
Проверка та же, что уже названа в приёмке: непрерывность по дням и сходимость
|
||
сумм с часовым слоем HAE на пересечении периодов. Не сошлось — пометки нет,
|
||
и это не отказ импорта, а честный отказ от обещания;
|
||
- пометка **ничего не удаляет**. Она только даёт устареванию нижнего слоя
|
||
основание; само удаление включается отдельно и позже.
|
||
|
||
**`stateOfMind` пометку не получает никогда** — его в экспорте Apple нет ни
|
||
одним типом (находка 42), источник у него единственный, и устаревание к нему
|
||
неприменимо. Это надо записать явно, а не оставить следовать из отсутствия
|
||
данных.
|
||
|
||
Готово, когда история за несколько лет лежит в слое `sample`, повторный импорт
|
||
не меняет ничего, суммы по слою сходятся с часовым слоем HAE на пересечении
|
||
периодов, а покрытые периоды помечены и видны без пересборки.
|
||
|
||
Архивы: `/home/av/MediaEverything/HealthData/apple_health/` — девять штук,
|
||
2021-12 … 2026-08. Старые версии формата годятся как регрессионный набор.
|