полнота точки — множество ключей, победитель — функция множества точек
- отношение победы было нетранзитивным: полнота (частичный порядок) плюс тай-брейк (тотальный) в попарной свёртке давали цикл, из-за которого одна и та же доставка меняла содержимое объекта при каждой пересборке - надмножество побеждает только при совпадении значений общих содержательных ключей: иначе точка без единого измерения вытесняла измерение - Less стал тотальным, isEmpty не материализует значение, имя метрики в координате столкновения обрезается, отпечаток витрины включает units и sealed - на живом архиве строгий no-op: 1737 объектов, содержимое совпало побайтово
This commit is contained in:
@@ -65,32 +65,129 @@ TBD - created by archiving change razbor-metrik-v-obekty. Update Purpose after a
|
||||
### Requirement: Разрешение столкновений по полноте
|
||||
|
||||
Когда по одним координатам приходят разные содержимые, система SHALL оставлять
|
||||
**более полную** точку — ту, у которой больше значащих полей, — а не последнюю
|
||||
пришедшую. Иначе бедная доставка стирает у богатой поля, которых сама не несёт:
|
||||
0.66% координат различаются именно набором полей при одинаковом значении.
|
||||
**более полную** точку — ту, чьё множество ключей с непустым значением является
|
||||
**строгим надмножеством** множества другой, — а не последнюю пришедшую. Иначе
|
||||
бедная доставка стирает у богатой поля, которых сама не несёт.
|
||||
|
||||
Если полнота равна, а значения различаются, исход MUST быть детерминированным
|
||||
и не зависеть от порядка, в котором доставки дошли до хранилища: свёртка по
|
||||
журналу обязана давать то же состояние, что приём в реальном времени.
|
||||
Полнота SHALL сравниваться множествами, а не их размером. Число сравнимо
|
||||
всегда, и потому счётчик даёт ответ там, где ответа нет: точка с пятью полями,
|
||||
не несущими содержания, побеждала бы настоящее измерение с двумя полями и
|
||||
стирала бы его безвозвратно.
|
||||
|
||||
Измерено (находка 49): настоящих столкновений 2 897 из 444 256 координат
|
||||
(0.65%); из них 981 различаются набором полей — это и есть область правила
|
||||
полноты, — 1 916 несут равные наборы и разные значения, где исход решает
|
||||
тай-брейк, а несравнимых наборов ноль.
|
||||
|
||||
Пустым значением MUST считаться `null`, пустая строка, число, равное нулю (в
|
||||
любой записи), пустой объект и пустой массив: поле без содержания не делает
|
||||
точку полнее точки, где этого поля нет вовсе. Пустота MUST определяться по
|
||||
разобранному значению, а не по байтам: `0`, `0.0`, `0e0`, `-0` и `{ }` — та же
|
||||
пустота, что `0` и `{}`.
|
||||
|
||||
`false` пустотой MUST NOT считаться: для булева поля это одно из двух значений,
|
||||
а не отсутствие содержания (`isIndoor: false` — тренировка на улице).
|
||||
|
||||
Поле `source` в множество не входит — оно нестабильно и переписывается задним
|
||||
числом (находка 36), так что о полноте измерения ничего не говорит.
|
||||
|
||||
Содержимое, которое не разбирается как JSON-объект, SHALL нести **пустое
|
||||
множество** ключей: так оно проигрывает любой точке с содержанием и не
|
||||
загрязняет наблюдение о несравнимых наборах.
|
||||
|
||||
Надмножество побеждает только тогда, когда оно **несёт то же содержание**:
|
||||
значения ключей, содержательных у обеих точек, MUST совпадать (с точностью до
|
||||
канонической формы). Иначе точки несут разные измерения, и надмножество имён
|
||||
о полноте не говорит ничего — такая пара MUST разрешаться как равнополная.
|
||||
Без этого условия точка `{date, qty:0.001, p1:null, p2:null}` вытесняла бы
|
||||
`{date, qty:72.5}`, то есть точка, где ни одно значение не измерение,
|
||||
стирала бы измерение — ровно то, ради отрицания чего правило переписано.
|
||||
|
||||
Если множества ключей с непустым значением **равны и значения совпали**,
|
||||
система SHALL сравнить множества **всех** ключей, кроме `source`, и оставить
|
||||
строгое надмножество. Без этого разряда правило теряло бы поля там, где
|
||||
заведено их беречь: точка `{date, qty:10, Min:0, Max:0}` и точка
|
||||
`{date, qty:10}` несут одинаковое содержание, и `Min` с `Max` исчезли бы из
|
||||
витрины по жребию. Несравнимость на этом разряде исходом MUST NOT быть:
|
||||
лишние ключи там заведомо пусты, объединять в них нечего.
|
||||
|
||||
Если равны и эти множества, а значения различаются, исход MUST быть
|
||||
детерминированным и не зависеть от порядка, в котором доставки дошли до
|
||||
хранилища: свёртка по журналу обязана давать то же состояние, что приём в
|
||||
реальном времени.
|
||||
|
||||
Победитель MUST быть функцией **множества** точек координаты, а не порядка их
|
||||
поступления. Попарная свёртка этого не даёт: полнота — частичный порядок,
|
||||
тай-брейк — тотальный, и вместе они образуют нетранзитивное отношение победы
|
||||
(A превосходит B по полноте, B бьёт C тай-брейком, C бьёт A тай-брейком).
|
||||
При таком цикле повторная свёртка одной и той же доставки меняет содержимое
|
||||
объекта, и витрина перестаёт быть функцией журнала. Поэтому система SHALL
|
||||
отбросить кандидатов, превзойдённых по полноте кем-то другим, и выбрать
|
||||
победителя среди оставшихся по тотальному порядку — обе операции зависят
|
||||
только от состава множества.
|
||||
|
||||
Сравнение по `received_at` для этого не годится: у сохранённой точки нет
|
||||
провенанса — ни времени приёма, ни идентификатора доставки, — и сравнивать
|
||||
не с чем. Детерминизм обеспечивается свойством самих значений (например,
|
||||
порядком канонических форм), а не порядком событий.
|
||||
|
||||
Если множества **несравнимы** — каждое несёт ключ с непустым значением,
|
||||
которого нет у другого, — система SHALL выбрать победителя тем же
|
||||
детерминированным правилом, что и при равных множествах, и MUST оставить
|
||||
наблюдение: счётчик в итоге разбора доставки, координаты объекта и запись
|
||||
`WARN` без значений точки. Несравнимый набор — частный случай столкновения:
|
||||
счётчик перезаписей растёт вместе с ним, а координаты попадают в оба списка.
|
||||
|
||||
Объединять поля двух точек система SHALL NOT: на живом потоке несравнимых
|
||||
наборов не встретилось ни разу (0 из 2 897 столкновений, при обоих определениях
|
||||
пустоты), и реализация правила, которое никогда не срабатывает, стоила бы
|
||||
больше, чем счётчик, который скажет, если оно наступит.
|
||||
|
||||
Победителем SHALL оставаться одна из пришедших точек **дословно**: правило
|
||||
выбирает, а не конструирует. Каноническая форма существует только в момент
|
||||
сравнения — вернуть её вместо исходных байт значило бы сохранить округлённое
|
||||
число вместо присланного.
|
||||
|
||||
#### Scenario: Бедная точка не стирает поля богатой
|
||||
|
||||
- **WHEN** сохранена точка с `Avg`, `Min`, `Max` и `context`
|
||||
- **AND** по тем же координатам приезжает точка только с `Avg`, `Min` и `Max`
|
||||
- **THEN** сохранённая точка остаётся с `context`
|
||||
|
||||
#### Scenario: Поля без содержания полноты не добавляют
|
||||
|
||||
- **WHEN** сохранена точка с пятью полями, значения которых `0`, `{}` и `[]`
|
||||
- **AND** по тем же координатам приезжает точка с `date` и ненулевым `qty`
|
||||
- **THEN** остаётся точка с `date` и `qty`
|
||||
|
||||
#### Scenario: При равном содержании поля не теряются
|
||||
|
||||
- **WHEN** сохранена точка `{date, qty, Min:0, Max:0}`
|
||||
- **AND** по тем же координатам приезжает точка `{date, qty}` с другим `qty`
|
||||
- **THEN** остаётся точка с `Min` и `Max`
|
||||
|
||||
#### Scenario: Одинаково полные точки с разными значениями
|
||||
|
||||
- **WHEN** по одним координатам приходят две одинаково полные точки с разными
|
||||
значениями
|
||||
- **WHEN** по одним координатам приходят две точки с одинаковыми множествами
|
||||
ключей и разными значениями
|
||||
- **THEN** исход определяется детерминированно и не зависит от порядка
|
||||
воспроизведения доставок
|
||||
|
||||
#### Scenario: Несравнимые множества считаются, а не сливаются
|
||||
|
||||
- **WHEN** по одним координатам приходят две точки, каждая из которых несёт
|
||||
ключ с непустым значением, которого нет у другой
|
||||
- **THEN** остаётся ровно одна точка, выбранная детерминированно
|
||||
- **AND** счётчик несравнимых наборов в итоге разбора доставки растёт
|
||||
- **AND** система пишет `WARN` с координатами объекта и без значений точки
|
||||
|
||||
#### Scenario: Содержимое, которое не разбирается в объект
|
||||
|
||||
- **WHEN** по координатам сталкиваются точка с непустыми полями и содержимое,
|
||||
не разбирающееся как JSON-объект
|
||||
- **THEN** остаётся точка с полями
|
||||
- **AND** счётчик несравнимых наборов не растёт
|
||||
|
||||
Столкновением SHALL считаться расхождение **канонических форм**, а не байтов.
|
||||
Байты нестабильны — ради этого канонизация и заведена: из 81 952 повторно
|
||||
приехавших точек 67 534 различаются лишь порядком ключей, ещё 63% — последним
|
||||
|
||||
Reference in New Issue
Block a user