feat(dds): добавлена модель заказа и пересборка окна заменой партиций
Зачем: - Дать слою первую физическую сущность и показать идемпотентность, устроенную иначе, чем в приёме: заменой партиции, а не колонкой версии. - Родить механику дневной пересборки на кластере — образец для сессий и витрин. Что: - Добавлены dds.order_rep/_dist, двойник-донор dds.order_stage_rep/_dist и публичный договор dds.order_v с разбором позиций в три массива. - Добавлены запросы объёма прогона, сборки в двойник и замены партиции по дню. - Добавлен даг dds_transform: группа задач order, замена — размноженной задачей. - Окно изменяемости K пришло на сторону стенда якорем compose; владелец числа остаётся у генератора. - Объём считается от позднейшего дня заказа и первого недостающего дня: ярлыки доставки ODS для этого непригодны, а максимум собранного дня прячет дыры. - Записано, чего конвейер о себе не знает, и адресовано контуру DQ. Проверка: - make lint - make smoke, make check-clickhouse, make check-services - Прогон по стартовому миру: 1917 заказов, счёт равен ods.order_v, каждый заказ на шарде своего cityHash64(order_id), сумма позиций равна items_total. - Повтор без нового слепка: содержимое то же, _load_id новый; после слепка пересобрано окно, день за окном не тронут. - Снесённая руками партиция 2026-06-01 восстановлена побайтово. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
96829718f9
commit
1e8b83ffbb
9 files changed
+555
-6
No files matched your search
@@ -41,12 +41,30 @@
|
||||
|
||||
Параметров у конвейера нет: объём он выводит сам из `world_position` и
|
||||
состояния слоёв. Сессии догоняют хвост — от последнего собранного дня до
|
||||
последнего прожитого; заказы пересобирают дышащее окно K от позиции; карта
|
||||
последнего прожитого; заказы пересобирают дышащее окно K и тот же хвост; карта
|
||||
идентичностей пересчитывается целиком; правила витрин — у
|
||||
[слоя DM](dm.md).
|
||||
Поэтому один и тот же запуск одинаково верен из триггера, с кнопки менти и
|
||||
после падения, а разгону на семь дней хватает одного прогона.
|
||||
|
||||
Окно заказов отсчитывается от **последнего дня, о котором рассказал сам
|
||||
источник**, — от позднейшего дня заказа в ODS. Рядом напрашиваются ещё два
|
||||
способа, и оба отвергнуты по одной причине: они отвечают не на тот вопрос.
|
||||
|
||||
Позиция мира говорит, какой день прожит, а не какой доехал: прогон дня D везёт
|
||||
слепок дня D − 1, да и позиция ставится раньше трансформации, так что после
|
||||
неудачного приёма она обгоняет хранилище. Слой обязан считать объём по тому,
|
||||
что у него есть, а не по тому, что мир о себе заявляет.
|
||||
|
||||
Ярлыки доставки — `snapshot_date`, `_load_id`, `_load_ts` — не отвечают тоже, и
|
||||
это свойство ODS, а не недосмотр: слой схлопывает доставки, сохраняя деловые
|
||||
версии, поэтому у заказа, который не менялся, ярлык выжившей строки достаётся
|
||||
жребием ([приём заказов](orders/ingestion.md), «Роль ODS»). Замер на стартовом
|
||||
мире: последний слепок нёс все 1662 заказа, а его ярлык сохранили 1188 —
|
||||
отбор «дни, у которых `snapshot_date` равен последнему» потерял бы четверть
|
||||
заказов и молча пропустил бы дальний край окна, где заказы давно замёрзли.
|
||||
К времени создания это не относится: у всех версий заказа оно одно.
|
||||
|
||||
## Готовность источника
|
||||
|
||||
Первый шаг `dds_transform` — дождаться, пока хвост топика `hits` дожёван:
|
||||
@@ -67,6 +85,31 @@
|
||||
замены: полная перезапись в `ReplacingMergeTree` — так живут карта
|
||||
идентичностей и витрина `daily_traffic` ([слой DM](dm.md)).
|
||||
|
||||
## Чего конвейер о себе не знает
|
||||
|
||||
Трансформация собирает слой по правилу, а не сверяет его с источником. Отсюда
|
||||
четыре вещи, которых она не заметит, и у всех четырёх один адрес — контур DQ.
|
||||
|
||||
- **Окно K разъехалось с источником.** Число живёт двумя копиями: у генератора
|
||||
в `world.py` и у стенда в `compose.yaml`. Разойдутся — слой начнёт
|
||||
недобирать край окна или переписывать замёрзший день, и оба прогона будут
|
||||
зелёными.
|
||||
- **Пустой свежий день сдвигает край окна.** Если в позднейший день источника
|
||||
не родилось ни одного заказа, окно съезжает на день назад
|
||||
([`sql/dds/order_scope.sql`](../../sql/dds/order_scope.sql)).
|
||||
- **Замена партиции прошла на одном шарде из двух.** День в слое есть — значит,
|
||||
объём следующего прогона его не тронет, а слой останется собранным наполовину
|
||||
из старого, наполовину из нового.
|
||||
- **Брак внутри `items` становится нулями.** Строгий приём внутрь позиций не
|
||||
смотрит, разбор по типу молчит, и цена без числа доедет до витрины выручки
|
||||
нулём ([`sql/dds/order_rebuild.sql`](../../sql/dds/order_rebuild.sql)).
|
||||
|
||||
Общее у них одно, и оно же подсказывает лекарство: ответить может только
|
||||
сверка слоя с источником по дню — счёт заказов и позднейший `updated_at` с
|
||||
обеих сторон. Трансформации такую сверку не поручают намеренно: она собирает,
|
||||
а проверяет другой. Так две роли остаются различимы, и ни одна не
|
||||
притворяется другой.
|
||||
|
||||
## Не входит
|
||||
|
||||
- Партиционная переобработка — переиграть произвольный прошлый день или
|
||||
|
||||
Reference in new issue
Block a user