добавлен словарь категориальных значений HAE → коды HealthKit
- фазы сна, контекст пульса и имена тренировок попадают в реестр `category_value` (миграция 00010): строка хранится дословно, выведенный код лежит рядом отдельной записью, а не полем внутри точки - словарь и синонимы кодов живут в бинаре (`internal/healthkit`); локаль из `Accept-Language` сужает поиск, но в ключ реестра не входит — заголовков в сыром архиве нет - наблюдение входит в отпечаток витрины, выведенный код — нет: он производная от словаря, а не от журнала
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
-- +goose Up
|
||||
-- Реестр категориальных значений: какие перечислимые строки поток приносил и
|
||||
-- какой у них стабильный код HealthKit.
|
||||
--
|
||||
-- HAE отдаёт фазу сна как «БДГ», контекст пульса как «Сидячий образ жизни», тип
|
||||
-- тренировки как «В помещении Ходьба» — строками локали телефона, а родной
|
||||
-- экспорт Apple говорит кодами (`HKCategoryValueSleepAnalysisAsleepREM`).
|
||||
-- Источники несопоставимы, и на этой сверке стоит устаревание нижнего слоя.
|
||||
-- Словарь фаз сна выведен сопоставлением потока с экспортом за тот же период
|
||||
-- (docs/research/apple-health.md, находка 43).
|
||||
--
|
||||
-- ПОЧЕМУ ОТДЕЛЬНАЯ ТАБЛИЦА, А НЕ ПОЛЕ РЯДОМ СО СТРОКОЙ В ТОЧКЕ. Точка хранится
|
||||
-- исходными байтами; дописать в неё ключ можно только пересериализацией, а она
|
||||
-- теряет литерал — ровно то, от чего эти байты и защищают. Параллельный массив
|
||||
-- кодов в `bucket` завёл бы производную величину в путь слияния и хеширования:
|
||||
-- правило полноты, тай-брейк и `content_hash` пришлось бы учить носить код, не
|
||||
-- давая ему влиять на исход. Это правка на поверхности critical-инвариантов
|
||||
-- ради нуля новых сведений — код есть функция от того, что уже лежит. И
|
||||
-- пополнение словаря переписывало бы каждый объект с фазами сна; здесь меняется
|
||||
-- десяток строк.
|
||||
--
|
||||
-- ПОЧЕМУ ЛОКАЛИ НЕТ В КЛЮЧЕ. Она приезжает заголовком `Accept-Language`, а
|
||||
-- заголовков в сыром архиве не лежит: они были заголовками запроса, а не телом.
|
||||
-- Доставка, восстановленная из осиротевшего тела, приходит без локали — и ключ
|
||||
-- с локалью положил бы вторую строку на то же значение, то есть состояние стало
|
||||
-- бы функцией от того, уцелела ли учётная строка. Ключ по трём полям — функция
|
||||
-- одних тел. На каком языке приехала строка, восстанавливается по доставке
|
||||
-- провенанса: `first_delivery_id` → `delivery.headers`.
|
||||
--
|
||||
-- ПОЧЕМУ ПРОВЕНАНС ТОЛЬКО ПЕРВОЙ ВСТРЕЧИ. Минимум по журналу идемпотентен при
|
||||
-- повторной свёртке той же доставки; счётчик встреч не идемпотентен и сделал бы
|
||||
-- состояние зависящим от числа прогонов. «Когда эта строка появилась впервые»
|
||||
-- отвечает на вопрос о смене языка телефона — «сколько раз» не отвечает ни на
|
||||
-- один заданный.
|
||||
--
|
||||
-- `code` — КЭШ. Он производная не от журнала, а от словаря в бинаре, и потому
|
||||
-- в отпечаток витрины не входит (см. Fingerprint): включённый туда, он заставил
|
||||
-- бы всякое пополнение словаря давать расхождение при побайтно совпавшем
|
||||
-- журнале, а человек, принимающий по отпечатку необратимое решение о подмене
|
||||
-- базы, читал бы это как дефект. Строка, переставшая приезжать, держит код
|
||||
-- прежнего словаря до пересборки — осознанная цена, названная вслух.
|
||||
--
|
||||
-- Пустой код — законное состояние: он означает «словарь этой строки не знает».
|
||||
-- Пустая строка, а не NULL: различать «кода нет» и «кода не считали» здесь
|
||||
-- нечем — вывод кода идёт на каждой встрече, и третьего состояния у него не
|
||||
-- бывает.
|
||||
--
|
||||
-- `WITHOUT ROWID`: обращение всегда по полному первичному ключу, а строк
|
||||
-- единицы — на живом потоке различных значений по всем трём полям около
|
||||
-- одиннадцати.
|
||||
--
|
||||
-- Data-миграции нет и быть не может: коды выводятся из ТЕЛ, а тела лежат в
|
||||
-- архиве, а не в базе. Реестр рабочей витрины наполняется по мере свёртки новых
|
||||
-- доставок и целиком — пересборкой. Отсюда первое расхождение отпечатков после
|
||||
-- выкатки: оно законно, и отчёт `reindex` называет его ожидаемым классом.
|
||||
CREATE TABLE category_value (
|
||||
metric TEXT NOT NULL,
|
||||
field TEXT NOT NULL,
|
||||
value TEXT NOT NULL,
|
||||
code TEXT NOT NULL,
|
||||
first_seen_utc TEXT NOT NULL,
|
||||
first_delivery_id TEXT NOT NULL,
|
||||
PRIMARY KEY (metric, field, value)
|
||||
) WITHOUT ROWID;
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE category_value;
|
||||
Reference in New Issue
Block a user