docs(specs): закрыты находки внешнего ревью спеки v2 (#17)
- Зачем:
- слепое ревью постановки нашло места, где исполнителю пришлось бы
молча изобретать решение.
- Что:
- зафиксированы: правило соединения purchaseID[1]=order_id, исключение
declared_* из правила «деньги по бэкенду», имена массивов позиций
dds.order, контракт присутствия всех 46 полей, класс awaiting_order
в сверке, счётчик дельт сумм в манифесте.
- шардирование в разделе 6 и dds.identity_map приведено к
cityHash64 — буквально тем же выражением, что в 1.3.
- Проверка:
- сверка правок с индексом находок ревью (SOL-1..SOL-8, кроме
отклонённого SOL-7).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -196,7 +196,9 @@ Ecommerce (заполнены только у торговых событий):
|
|||||||
|
|
||||||
Пропущенный день ничего не ломает, следующий слепок самовосстанавливает.
|
Пропущенный день ничего не ломает, следующий слепок самовосстанавливает.
|
||||||
- Разбор JSON-позиций — **один раз**, в трансформации ODS → DDS; дальше
|
- Разбор JSON-позиций — **один раз**, в трансформации ODS → DDS; дальше
|
||||||
витрины работают с плоскими массивами. Это единственный носитель навыка
|
витрины работают с плоскими массивами `dds.order`: `item_sku`
|
||||||
|
Array(String), `item_qty` Array(UInt64), `item_price` Array(Decimal(18,2))
|
||||||
|
— одной длины, порядок как в JSON. Это единственный носитель навыка
|
||||||
«вложенный JSON в ClickHouse» на стенде.
|
«вложенный JSON в ClickHouse» на стенде.
|
||||||
- Статусы держим все три: смена `created` → `paid` и есть причина «дыхания»
|
- Статусы держим все три: смена `created` → `paid` и есть причина «дыхания»
|
||||||
выручки внутри окна; сужение до двух — резервный срез 1.
|
выручки внутри окна; сужение до двух — резервный срез 1.
|
||||||
@@ -212,7 +214,10 @@ CSV в репозитории (`data/catalog/products.csv`: `sku`, `name`, `cate
|
|||||||
## 4. Сверка `purchase` против заказов
|
## 4. Сверка `purchase` против заказов
|
||||||
|
|
||||||
Ключ: клиентский `purchaseID` = `order_id` бэкенда (магазин знает номер
|
Ключ: клиентский `purchaseID` = `order_id` бэкенда (магазин знает номер
|
||||||
заказа на `/confirmation`). Расхождения — перечислимый список,
|
заказа на `/confirmation`). У события `purchase` массив `purchaseID` несёт
|
||||||
|
ровно один элемент (одно подтверждение — один заказ), сверка соединяет по
|
||||||
|
`purchaseID[1]`; правило зафиксировать комментарием в SQL сверки.
|
||||||
|
Расхождения — перечислимый список,
|
||||||
детерминированный от seed, не хаос:
|
детерминированный от seed, не хаос:
|
||||||
|
|
||||||
| | Расхождение | Механика в генераторе | Ориентир доли |
|
| | Расхождение | Механика в генераторе | Ориентир доли |
|
||||||
@@ -235,7 +240,10 @@ CSV в репозитории (`data/catalog/products.csv`: `sku`, `name`, `cate
|
|||||||
механически дублирует B.
|
механически дублирует B.
|
||||||
|
|
||||||
Правило стенда: **поведение и атрибуцию считаем по трекеру, деньги — по
|
Правило стенда: **поведение и атрибуцию считаем по трекеру, деньги — по
|
||||||
бэкенду**. Оно выучивается на конфликте: суммы не сойдутся, менти сам
|
бэкенду**. Единственное разрешённое исключение — клиентская оценка выручки
|
||||||
|
под именем `declared_*` там, где атрибуция без трекера невозможна (UTM);
|
||||||
|
слово `declared` в имени — сигнал «это заявка клиента, не деньги
|
||||||
|
отчётности». Оно выучивается на конфликте: суммы не сойдутся, менти сам
|
||||||
раскопает почему (Float64 против Decimal, промокод, доставка, отмены).
|
раскопает почему (Float64 против Decimal, промокод, доставка, отмены).
|
||||||
|
|
||||||
## 5. Анонимность и склейка идентичностей
|
## 5. Анонимность и склейка идентичностей
|
||||||
@@ -286,7 +294,10 @@ CSV в репозитории (`data/catalog/products.csv`: `sku`, `name`, `cate
|
|||||||
`cityHash64(сырой строки)`. Урок: «какая нода читала топик — меняется между
|
`cityHash64(сырой строки)`. Урок: «какая нода читала топик — меняется между
|
||||||
прогонами, куда легли данные — нет».
|
прогонами, куда легли данные — нет».
|
||||||
- **Приём строгий**: `input_format_skip_unknown_fields = 0`, обязательные
|
- **Приём строгий**: `input_format_skip_unknown_fields = 0`, обязательные
|
||||||
поля — без значений по умолчанию. Несовпадение имени поля — громкая
|
поля — без значений по умолчанию. Контракт присутствия: генератор выдаёт
|
||||||
|
**все 46 полей в каждом событии**; «пусто» — пустой массив, пустая строка
|
||||||
|
или 0, а не отсутствие ключа в JSON. Так строгий приём уживается с
|
||||||
|
полями, пустыми по смыслу (ecommerce у `pageview`, UTM у прямого захода). Несовпадение имени поля — громкая
|
||||||
ошибка в `*_errors`, а не молчаливые нули: имена CamelCase регистрозависимы,
|
ошибка в `*_errors`, а не молчаливые нули: имена CamelCase регистрозависимы,
|
||||||
опечатка иначе не падает.
|
опечатка иначе не падает.
|
||||||
- **Политика соединений**: по ключу ко-локации — обычное соединение с
|
- **Политика соединений**: по ключу ко-локации — обычное соединение с
|
||||||
@@ -370,8 +381,11 @@ Kafka переобработка возможна только из эталон
|
|||||||
в порядке приоритета — классы пересекаются, побеждает более ранний).
|
в порядке приоритета — классы пересекаются, побеждает более ранний).
|
||||||
`match` — большинство строк; `amount_delta` — только необъяснённый остаток
|
`match` — большинство строк; `amount_delta` — только необъяснённый остаток
|
||||||
после приведения к сравнимой базе (округления Float64, ~1–2% заказов).
|
после приведения к сравнимой базе (округления Float64, ~1–2% заказов).
|
||||||
Строка «`purchase` без заказа» внутри живого окна — это опоздание, ждущее
|
Строка «`purchase` без заказа» внутри живого окна — опоздание, ждущее
|
||||||
слепка, а не отдельный класс расхождения.
|
слепка, а не расхождение: она получает служебный класс `awaiting_order`
|
||||||
|
(шестое значение `mismatch_class`, вне приоритетов расхождений). После
|
||||||
|
закрытия окна K таких строк не остаётся — сироты исключены построением
|
||||||
|
(раздел 4).
|
||||||
- **`v_utm_effectiveness`** — остаётся клиентской (атрибуция по трекеру);
|
- **`v_utm_effectiveness`** — остаётся клиентской (атрибуция по трекеру);
|
||||||
счётчики `purchases`/`add_to_carts` оживают из таксономии, добавляется
|
счётчики `purchases`/`add_to_carts` оживают из таксономии, добавляется
|
||||||
`declared_revenue` по UTM.
|
`declared_revenue` по UTM.
|
||||||
@@ -398,7 +412,7 @@ Kafka переобработка возможна только из эталон
|
|||||||
Манифест расширяется контрольными числами:
|
Манифест расширяется контрольными числами:
|
||||||
|
|
||||||
- заказная сторона: заказы и выручка по дням; манифест хранит точные
|
- заказная сторона: заказы и выручка по дням; манифест хранит точные
|
||||||
счётчики по каждому классу расхождений (отмены, потери, дубли) —
|
счётчики по каждому классу расхождений (отмены, потери, дубли, дельты сумм) —
|
||||||
самопроверка лабы сверки;
|
самопроверка лабы сверки;
|
||||||
- идентичность: uniq кук, uniq известных пользователей, число двухкуковых
|
- идентичность: uniq кук, uniq известных пользователей, число двухкуковых
|
||||||
покупателей — лаба склейки получает самопроверку.
|
покупателей — лаба склейки получает самопроверку.
|
||||||
@@ -469,7 +483,8 @@ v2 стартует пустым, поэтому объём ниже — это
|
|||||||
9. Мониторинг и runbook «keeper упал / DDL повис в очереди».
|
9. Мониторинг и runbook «keeper упал / DDL повис в очереди».
|
||||||
|
|
||||||
Критерий приёмки этапа — честный: `make up` работает и проходят
|
Критерий приёмки этапа — честный: `make up` работает и проходят
|
||||||
smoke-проверки, а не «дашборд зелёный». Документация правится в PR этапа
|
smoke-проверки, а не «дашборд зелёный». Это минимальная планка; свои
|
||||||
|
наблюдаемые критерии каждый этап получает при разбиении в /to-tickets. Документация правится в PR этапа
|
||||||
(правило AGENTS.md).
|
(правило AGENTS.md).
|
||||||
|
|
||||||
## 10. Границы: чего не делаем
|
## 10. Границы: чего не делаем
|
||||||
|
|||||||
Reference in New Issue
Block a user