Модель заказа в DDS: dds.order и пересборка окна #151
Notifications
Due Date
No due date set.
Blocks
Depends on
#152 Сессии: dds.session и нарезка визитов
ddmitry/clickstream-data-platform
#153 Карта идентичностей: dds.identity_map и полный пересчёт
ddmitry/clickstream-data-platform
#150 Контракт события: представление dds.event_v
ddmitry/clickstream-data-platform
Reference: ddmitry/clickstream-data-platform#151
Reference in new issue
Block a user
Part of #6.
Цель
Физическая модель заказа:
dds.order_rep/_dist/_vи перваятрансформация слоя — пересборка «дышащих» дней из
ods.order_vзаменойпартиций. Здесь же рождаются даг
dds_transformи механика заменыпартиции на кластере — образец для сессий и витрин. Учебный результат
(order.md): идемпотентность, устроенная иначе, чем в приёме, — заменой
партиции, а не версиями.
Что войдёт
dds.order_rep—ReplicatedMergeTreeбез колонки версии, партицияorder_date, ключсортировки
order_id;dds.order_dist— шардированиеcityHash64(order_id);dds.order_v. Отдельный грант не нужен:bi_readerуже читаетdds.*по ADR 0007.order_dateипозиции-массивы — по order.md; служебные
_load_id/_load_tsсобравшего запуска.
sql/dds/по конвенции раскладки SQL. Объём — дышащиедни плюс дни, которых в слое ещё нет: первая сборка собирает весь
стартовый мир (правило etl.md — объём из позиции и состояния слоёв).
Дышащие дни не выводить арифметикой «K дней от
world_position»:слепки запаздывают на день, и такой счёт промахивается по краям окна;
дышащие дни — ровно те, которые принёс последний принятый слепок,
вывод множества зафиксировать комментарием в SQL. Сбор — в таблицу-двойник, затем
REPLACE PARTITIONON CLUSTER по локальным таблицам (storage.md, «Что проверено»: по
Distributedоперации с партициями отвечают кодом 48); формадвойника — правило партиции-донора; вставка в
_dist— с осознаннымparallel_distributed_insert_select(капкан #137).генераторе (
ORDER_WINDOW_DAYS); K — константа мира, не параметр(спека §9, срез 3); где ей жить на стороне дагов — решить здесь.
dds_transformпо образцуorders_ingest: без расписания, одинактивный прогон, первая задача — заказы, имя задачи — имя сущности;
параметров нет.
комментарием. Таблица DDL-файлов в storage.md — тем же PR.
Границы
etl_pipelineипути запуска — тикет конвейера: пока
dds_transformзапускается рукой.техдолг #2.
Кому что
Модельный DDL и SQL пересборки — Opus. Codex — опыты по брифу: повтор
прогона, «дыхание» статусов внутри окна, уборка за опытами (testing.md).
Сначала прочитать
правило донора), «Служебные колонки», «Раскладка SQL», «Что проверено»;
ods.order_v.Проверка
make lint; на стендеmake smoke,make check-clickhouseиmake check-services(родился даг) зелёные.dds.order_vесть за все днимира, счёт равен
ods.order_v(обе стороны — по Distributed); каждыйзаказ — на шарде своего
cityHash64(order_id).по массивам равна
items_total— инвариант бэкенда.dds.order_vне изменилось,
_load_idпересобранных дней — новый._load_idновый), прочие дни не тронуты (их_load_idпрежний).bi:dds.order_v,_repи_distпроходят;чтение STG отклоняется.
Готово, ветка
151-dds-order-model.Что сделано
sql/ddl/45-dds-tables.sql—dds.order_rep/_distи двойникdds.order_stage_rep/_dist, донор партиций;dds.order_vдобавлено в50-dds-views.sql.sql/dds/— три запроса: объём прогона, сборка в двойник, замена партиции.dags/dds_transform.py— группа задачorder: объём, сборка, замена по днюразмноженной задачей.
compose.yaml.Решения по развилкам тикета
Вывод дышащих дней. Отбор по
snapshot_dateстрок отвергнут: унеизменившегося заказа ярлык выжившей версии — жребий. Замер на стартовом
мире: последний слепок нёс все 1662 заказа, ярлык последнего слепка сохранили
1188. Окно считается от позднейшего дня заказа в ODS плюс K; вывод и замер — в
sql/dds/order_scope.sqlиetl.md.Где живёт K. Копией в
compose.yaml, владелец числа —generator/world.py.Опись мира как единый источник отвергнута: хранилище не должно читать артефакт
сборки источника. Риск дрейфа назван и передан контуру DQ.
Двойник. Рядом с целью в
dds, отдельная база не заводилась:storage.mdуже держит позицию «право доступа шире договора».
Ревью
Слепое ревью Codex (свежий тред, 100 команд, все шесть критериев перепроверены
независимо): шесть находок,
CHANGES_REQUIRED. Исправлено четыре, две принятыс доводом.
Главная — прогресс слоя считался по
max(order_date), и упавшая заменаоставляла дыру, которую следующий прогон не видел. Проверено на живых данных:
партиция
2026-06-01снесена руками, старая формула отдала06-02 … 06-08(дыра навсегда), новая —
06-01 … 06-08; после прогона день восстановилсяпобайтово, отпечаток
16124F97EAE696C9совпал,_load_idновый.Остаток той же находки — половинчатая замена по шардам, когда
ON CLUSTERпрошёл на одном шарде из двух, — сюда не чинится: день в слое присутствует, и
отличить его может только сверка с источником. Вместе с дрейфом K, сдвигом
края окна на пустом дне и молчаливыми нулями в
itemsэто записано вetl.md, раздел «Чего конвейер о себе не знает», и адресовано контуру DQ.Хвост
Заведён #163: координаты доставки в ODS — ярлык, которому нельзя верить.
Три из шести находок ревью оказались процентами по этому долгу.
Влито в main: PR #164 (коммиты
1e8b83f,535b037). Все критерии приёмки отмечены. Хвост — #163.