- находки 48 и 49: единицы не менялись ни разу; настоящих столкновений 0.65%, несравнимых наборов полей нет, тай-брейк берёт меньшее в 96% случаев - edinicy-metriki-v-razreze закрыт: гипотеза не подтвердилась замером - тай-брейк отложен до каталога рода агрегации
73 lines
5.1 KiB
Markdown
73 lines
5.1 KiB
Markdown
# Полнота точки — по множеству ключей, а не по их числу
|
||
|
||
**Приоритет:** высокий
|
||
|
||
Была блокером, вынутым ревью кода задачи `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](rod-agregacii-i-katalog.md). Тай-брейк
|
||
доделывается **после** неё, отдельной задачей.
|
||
|
||
## Что стоит без решения
|
||
|
||
Ничего. Правило работает и **наблюдаемо**: столкновение считается расхождением
|
||
канонических форм (а не байтов), даёт `WARN` с координатами объекта и счётчик
|
||
`overwrites`.
|