Files
healthlog/docs/backlog/identichnost-trenirovok-pri-importe.md
T
av f8200f7f80 feat: разбор и хранение тренировок и состояния разума
- секции `workouts` и `stateOfMind` покрыты разбором: тренировка лежит одной
  строкой вместе с маршрутом и внутренними рядами, запись — по ключу `род + id`;
  миграция 00007 заводит обе таблицы и возвращает в очередь `partial`-доставки
  с этими ключами
- сущность заменяется целиком, но условно: приехавшая побеждает, если не теряет
  содержания сохранённой (множество ключей и длины верхнеуровневых массивов), а
  при равном содержании выигрывает версия из более поздней доставки ЖУРНАЛА —
  «побеждает приехавшая» было бы функцией порядка свёртки, и живая витрина
  расходилась бы с пересборкой молча
- отпечаток витрины покрывает тренировки и записи и снимается одним снимком
  базы; отчёт `reindex` считает «было и стало» по каждой единице хранения
2026-08-02 13:05:16 +03:00

3.1 KiB
Raw Blame History

Идентичность тренировок при импорте родного экспорта

Приоритет: средний

Тренировка в витрине адресуется своим id из HealthKit — его шлёт HAE. В export.xml этого идентификатора нет вовсе: у элемента Workout только тип, источник, даты и статистика. Значит healthlog import не сможет сопоставить тренировку из снапшота с той же тренировкой, уже приехавшей от HAE, и они задвоятся.

Это ровно та дыра, что была у точек, и там её закрыли ключом start + end (находка 47): HKObject.uuid в выгрузку не попадает, поэтому модель идентичности обязана выражаться через интервал.

Prior art: dogsheep/healthkit-to-sqlite адресует тренировку хешем содержимого (hash_id в sqlite-utils) — ровно потому, что идентификатора в экспорте нет. Нам это не подходит в лоб: у нас половина тренировок уже лежит под настоящим id, и хеш содержимого дал бы третий ключ рядом с двумя.

Варианты, которые надо будет сравнить:

  • Второй уникальный ключ (start_utc, end_utc) у тренировки: импорт ищет по нему, HAE — по id. Цена: индекс и вопрос, что делать при столкновении двух разных тренировок с одним интервалом (бывает ли такое — неизвестно).
  • Сопоставление на стадии импорта, без изменения схемы: импорт читает уже сохранённые тренировки за период и приписывает найденным их id. Цена: логика сопоставления живёт в импорте и не проверяется ничем, кроме него.
  • Считать тренировки из экспорта отдельным родом и не сопоставлять вовсе. Цена: потребитель видит две тренировки вместо одной и обязан схлопывать сам — ровно то, чего проект старается не делать.

Решать до появления формы healthlog import значит угадывать: неизвестно, понадобятся ли тренировки из экспорта вообще (у HAE они полнее — с маршрутом и рядами, а в экспорте маршрут лежит отдельными GPX).

Связано: docs/architecture.md → «Тренировки и прочие секции», задача import-eksporta-apple.