feat(dds): модель заказа и пересборка окна заменой партиций #164

Merged
ddmitry merged 2 commits from 151-dds-order-model into main 2026-08-26 12:36:11 +03:00
Owner

Закрывает #151.

Что внутри

Физическая модель заказа в DDS и первая трансформация слоя — пересборка
«дышащих» дней заменой партиции. Здесь же рождается даг dds_transform и
механика замены на кластере, образец для сессий и витрин.

Развилки и решения

Вывод дышащих дней. Отбор по snapshot_date строк отвергнут: у
неизменившегося заказа ярлык выжившей версии — жребий. Замер на стартовом мире:
последний слепок нёс все 1662 заказа, ярлык последнего слепка сохранили 1188.
Объём считается от позднейшего дня заказа плюс окно K, а хвост — от первого
недостающего
дня, а не от последнего собранного: иначе упавшая замена
оставляет дыру, которую следующий прогон не видит.

Где живёт K. Копией в compose.yaml, владелец числа — generator/world.py.
Опись мира как единый источник отвергнута: хранилище не должно читать артефакт
сборки источника. Риск дрейфа назван и адресован контуру DQ.

Двойник. Рядом с целью в dds; отдельная база не заводилась — storage.md
уже держит позицию «право доступа шире договора».

Проверка

make lint; на стенде smoke 21/0, check-clickhouse 10/10, check-services 7/0.
Все шесть критериев приёмки тикета проверены на живых данных и отмечены.

Отдельно проверена живучесть: партиция 2026-06-01 снесена руками, старая
формула объёма отдавала 06-02 … 06-08 (дыра навсегда), новая — 06-01 … 06-08;
после прогона день восстановился побайтово, отпечаток совпал, _load_id новый.

Ревью

Слепое ревью Codex свежим тредом: 100 команд, все критерии перепроверены
независимо, шесть находок, CHANGES_REQUIRED. Четыре исправлены, две приняты с
доводом; узкая перепроверка тем же ревьюером пройдена.

Остаток одной находки — половинчатая замена, когда ON CLUSTER прошёл на одном
шарде из двух, — сюда не чинится осознанно: день в слое присутствует, и увидеть
это может только сверка с источником. Вместе с дрейфом K, сдвигом края окна на
пустом дне и молчаливыми нулями в items записано в etl.md, раздел «Чего
конвейер о себе не знает».

Хвост

Заведён #163: координаты доставки в ODS — ярлык, которому нельзя верить. Три из
шести находок ревью оказались процентами по этому долгу.

Закрывает #151. ## Что внутри Физическая модель заказа в DDS и первая трансформация слоя — пересборка «дышащих» дней заменой партиции. Здесь же рождается даг `dds_transform` и механика замены на кластере, образец для сессий и витрин. ## Развилки и решения **Вывод дышащих дней.** Отбор по `snapshot_date` строк отвергнут: у неизменившегося заказа ярлык выжившей версии — жребий. Замер на стартовом мире: последний слепок нёс все 1662 заказа, ярлык последнего слепка сохранили 1188. Объём считается от позднейшего дня заказа плюс окно K, а хвост — от **первого недостающего** дня, а не от последнего собранного: иначе упавшая замена оставляет дыру, которую следующий прогон не видит. **Где живёт K.** Копией в `compose.yaml`, владелец числа — `generator/world.py`. Опись мира как единый источник отвергнута: хранилище не должно читать артефакт сборки источника. Риск дрейфа назван и адресован контуру DQ. **Двойник.** Рядом с целью в `dds`; отдельная база не заводилась — `storage.md` уже держит позицию «право доступа шире договора». ## Проверка `make lint`; на стенде smoke 21/0, check-clickhouse 10/10, check-services 7/0. Все шесть критериев приёмки тикета проверены на живых данных и отмечены. Отдельно проверена живучесть: партиция `2026-06-01` снесена руками, старая формула объёма отдавала `06-02 … 06-08` (дыра навсегда), новая — `06-01 … 06-08`; после прогона день восстановился побайтово, отпечаток совпал, `_load_id` новый. ## Ревью Слепое ревью Codex свежим тредом: 100 команд, все критерии перепроверены независимо, шесть находок, `CHANGES_REQUIRED`. Четыре исправлены, две приняты с доводом; узкая перепроверка тем же ревьюером пройдена. Остаток одной находки — половинчатая замена, когда `ON CLUSTER` прошёл на одном шарде из двух, — сюда не чинится осознанно: день в слое присутствует, и увидеть это может только сверка с источником. Вместе с дрейфом K, сдвигом края окна на пустом дне и молчаливыми нулями в `items` записано в `etl.md`, раздел «Чего конвейер о себе не знает». ## Хвост Заведён #163: координаты доставки в ODS — ярлык, которому нельзя верить. Три из шести находок ревью оказались процентами по этому долгу.
ddmitry added 1 commit 2026-08-26 12:21:13 +03:00
Зачем:
- Дать слою первую физическую сущность и показать идемпотентность, устроенную
  иначе, чем в приёме: заменой партиции, а не колонкой версии.
- Родить механику дневной пересборки на кластере — образец для сессий и витрин.

Что:
- Добавлены 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>
ddmitry added 1 commit 2026-08-26 12:32:10 +03:00
Зачем:
- Полный разбор урока про идемпотентность стоял дважды, предупреждение про
  окно K — трижды; внимание менти конечно, и каждый пересказ списывается
  с этого счёта.

Что:
- Докстринг dds_transform сокращён до одной фразы с указателями: полный разбор
  остался в шапке DDL, механика подмены — в order_replace.sql.
- Комментарий про ORDER_WINDOW_DAYS в даге сведён к указателю на compose,
  где число объявлено и где записан риск расхождения.
- Прорежен повтор одного риторического приёма «это не X» — оставлен там,
  где различие и есть суть.

Проверка:
- make lint, make config-test
- Прогон dds_transform зелёный, слой сходится с ods.order_v: 1917 заказов,
  8 дней.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ddmitry merged commit 9ab43e79cc into main 2026-08-26 12:36:11 +03:00
ddmitry deleted branch 151-dds-order-model 2026-08-26 12:36:11 +03:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ddmitry/clickstream-data-platform#164