Files
healthlog/docs/backlog/pravilo-sliyaniya-tochek.md
T
av 349a227ab1 блокеры разобраны замером: три стали задачами, один закрыт
- находки 48 и 49: единицы не менялись ни разу; настоящих столкновений 0.65%,
  несравнимых наборов полей нет, тай-брейк берёт меньшее в 96% случаев
- edinicy-metriki-v-razreze закрыт: гипотеза не подтвердилась замером
- тай-брейк отложен до каталога рода агрегации
2026-08-01 19:33:47 +03:00

5.1 KiB

Полнота точки — по множеству ключей, а не по их числу

Приоритет: высокий

Была блокером, вынутым ревью кода задачи razbor-metrik-v-obekty (профиль deep, находка №7 триажа, severity major). Решение принято замером (находка 49) — ниже задача на остаток.

Что не так сегодня

Полнота — это счётчик ключей, чьё значение не null, не "" и не пусто. Поэтому {}, [], 0 и false считаются содержательными:

точка {"qty":0,"a":0,"b":0,"c":{},"d":[]}   полнота 5
точка {"date":"…","qty":123.4}              полнота 2

Вторая точка — настоящее измерение — проигрывает первой и стирается безвозвратно. Восстановить можно только из сырого архива, пока он жив.

Что решено и на каком основании

Замер по всем 99 доставкам (находка 49): настоящих столкновений 2 897 из 444 256 координат (0.65%), и среди них ноль несравнимых наборов полей.

Отсюда:

  • Полнота — сравнение множеств ключей, побеждает надмножество. Ровно 981 случай из замера, и там правило уже работает верно — но работает случайно, через счётчик, который на другом входе даст обратное.
  • Объединение полей при несравнимых наборах не нужно. Самая дорогая часть обсуждавшегося варианта (1) на живом потоке не срабатывает ни разу. Вместо реализации — счётчик: несравнимый набор считается и логируется WARN. Если событие когда-нибудь наступит, оно будет видно, а не додумано заранее.
  • Тай-брейк при равной полноте в эту задачу не входит. Обоснование ниже.

Что делать

  1. resolve в internal/store/bucket.go: полнота — множество ключей с непустым значением; побеждает строгое надмножество.
  2. Несравнимые множества — счётчик в MergeStats плюс WARN с координатами объекта (без значений). Точку выбирает тот же тай-брейк, что и при равной полноте.
  3. Дельта-спека openspec/specs/storage → «Разрешение столкновений по полноте»: переформулировать с числа ключей на множество.
  4. Тесты: «бедная точка с пятью пустыми полями не стирает измерение» (регрессия на приведённой выше паре), «надмножество побеждает», «несравнимые наборы считаются».
  5. task verify:archive обязан дать то же состояние — правило меняет исход только там, где сегодня он неверен.

Что отложено и почему

Тай-брейк при равной полноте. Сегодня это лексикографический порядок канонических форм. Измерено (находка 49): в 1 847 случаях из 1 912 он выбирает меньшее значение — 96%. Четыре из шести затронутых метрик накопительные, там это систематический недосчёт; но крупнейшая группа, heart_rate (985 случаев), мгновенная, и там «большее» не правильнее.

То есть правильный тай-брейк зависит от рода метрики, а род по замыслу проекта измеряется сверкой слоёв между собой. Выбирать его сейчас — угадывать ровно то, что станет известно точно.

Зависимость: rod-agregacii-i-katalog. Тай-брейк доделывается после неё, отдельной задачей.

Что стоит без решения

Ничего. Правило работает и наблюдаемо: столкновение считается расхождением канонических форм (а не байтов), даёт WARN с координатами объекта и счётчик overwrites.