Зачем: помочь начинающему инженеру проследить событие и версию заказа
от генератора до хранилища, включая ошибки и повторные поступления.
Что: обновлены вводная генератора, справочники приема и модели заказа,
разделы хранилища и комментарии SQL и дага. Сохранены технические условия;
исполняемый код, схемы и поведение стенда не изменены.
Проверка: make lint, git diff --check, 142 локальные ссылки и справка CLI.
SQL без комментариев и Python AST без строк документации совпали
с исходными. Генерация данных и сброс состояния не выполнялись.
Refs #250
Зачем: выражения «собираются в донор» и «публикуются дни» требовали
знать устройство конвейера до чтения объяснения.
Что: описаны назначение промежуточных таблиц и последовательность
расчета, записи и замены разделов. Перечитаны остальные объяснения:
выбор дней, разворачивание позиций заказа, проверка сессий и повтор запуска.
Проверка: make lint, git diff --check, локальные ссылки и якоря.
SQL без комментариев и AST обоих дагов без строк документации не изменились.
Refs: #249
Зачем: читателю ступеней 1–4 нужно проследить выбор дней, расчет строки
и публикацию результата без расшифровки метафор.
Что: согласованы справочники DM, сессий, ETL и два раздела хранилища
с комментариями шести SQL-примеров. Уточнены ограничения повторного
запуска и выбора атрибутов при равном времени событий.
Проверка: make lint, git diff --check, локальные Markdown-ссылки и якоря.
SQL без комментариев совпадает; AST Python без строк документации совпадает.
Исторические разделы и материалы вне границ задачи сохранены.
Refs: #249
- Зачем:
- справочники читает человек со стороны, а «пульт мира», «опись мира»,
«работник» и «сырьё» звучали шуткой или калькой времён разработки
(тикет #214, выбор владельца).
- Что:
- CONTEXT.md: статьи «Паспорт мира», «Даги модельного времени»,
«Шаговый даг», «Сырые данные», старые слова в строках «Избегать»;
пометки в ADR 0005, 0008, 0009 без переписывания решений.
- замены по README, справочникам, путеводителю, лабам, спекам,
комментариям дагов и SQL, тегу дага и панели Grafana; имена в коде
не тронуты.
- world.md и stand.md: 35 находок вычитки внесены, регистр выровнен.
- Проверка:
- make config-test; make lint в корне и в generator/; make test в
generator/ (437 passed); скрипт ссылок из #212 пуст; grep старых
слов вне ADR, research и CONTEXT.md пуст.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QBCtU38qSHg5DvgtnKXcW
Зачем:
- Один запуск должен одинаково работать из жизненного цикла, вручную после разгона и повторно после отказа.
Что:
- Добавлена последовательная сцепка DDS и DM с ожиданием каждого слоя.
- DDS дожидается смещений Kafka и очереди доставки ClickHouse за общий срок.
- ETL встроен в создание мира и живой день; документация приведена к новому графу.
Проверка:
- make config-test; make lint.
- make smoke: 21/21; make check-clickhouse: 10/10; make check-services: 7/7.
- make rebuild-storage, живой и пакетный дни, искусственный отказ и ручное восстановление ETL.
- Зачем:
- реализованы требования issue #153 к мосту между кукой и пользователем.
- Что:
- добавлены физическая карта, точное представление и полный пересчёт через GLOBAL JOIN.
- задача identity_map поставлена после сборки заказов в dds_transform.
- устройство и живые проверки карты записаны в документации хранилища.
- Проверка:
- make lint, make smoke, make check-clickhouse, make check-services.
- три запуска dds_transform: 4770 физических строк и 1590 уникальных пар в _v.
- Зачем:
- ярлык snapshot_date выжившей строки доставался жребием, а объём
пересборки DDS держался на константе окна с двумя несверяемыми копиями
(ADR 0014, развилка #163).
- Что:
- ods.order_rep переведена на ReplacingMergeTree(snapshot_date): выживает
строка позднейшего слепка, ярлык стал правдивым.
- order_scope.sql выводит окно из дней последнего слепка; ORDER_WINDOW_DAYS
и параметр window_days сняты со стенда, мёртвая защита краем источника
убрана.
- документы и комментарии SQL приведены к ADR 0014: роль ODS, условие
«одна дата — один слепок», объём прогона и слепые пятна конвейера.
- Проверка:
- make lint; make rebuild-storage, затем make smoke, make check-clickhouse,
make check-services — зелёные.
- после двух слепков snapshot_date всех 1917 строк ods.order_v равен
последнему слепку заказа, расхождений ноль; деловые поля построчно
совпали с эталоном argMax по updated_at из сырья.
- dds_transform без K: первый прогон 06-01…06-07, после нового дня мира
06-02…06-08, повтор прогона содержимого не изменил.
Closes#165
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Зачем:
- Дать слою расчётную сущность, которой в потоке нет: стенд режет визиты сам,
а VisitID генератора остаётся эталоном самопроверки.
- Отделить прожитый день от живого — иначе визит, начатый в 23:50, замёрз бы
обрезанным навсегда: пересобирать замёрзший день слой не станет.
Что:
- Добавлены dds.session_rep/_dist, двойник-донор dds.session_stage_rep/_dist и
публичный договор dds.session_v.
- Нарезка стоит на двух окнах: первое ставит шов там, где пауза длиннее
тридцати минут, второе считает нарастающий итог швов — номер визита. Границу
суток держит разбиение окна, отдельной проверки ей не нужно.
- Порядок в окнах полный, по метке времени и event_id: сортировок две, и при
равных метках они разошлись бы, разорвав сессию надвое.
- Объём прогона считается от первой дыры в слое по последний прожитый день;
прожитый день выводится из позиции мира и первого дня событий. Собирать
нечего — группа задач пропускается, а не зеленеет впустую.
- В dds_transform появилась группа session рядом с заказом; зависимости по
данным между ними нет.
- Потолок max_active_tasks: размноженная замена без него выносит планировщика
за отведённые ему 640 МиБ.
- parallel_distributed_insert_select у сессий не назначается вслух — ключ
шардирования у источника и цели один по контракту ко-локации.
- Записано, что позиция отвечает за «прожит», а не за «доехал»: сторож хвоста
потока приезжает отдельным тикетом.
Проверка:
- make lint
- make smoke (21 проверка), make check-clickhouse (10), make check-services
- Стартовый мир, пересобранный с нуля: 79367 сессий за восемь дней;
расхождение с uniqExact(VisitID) по паре «кука × день» — ноль; все 401185
событий ровно в одной сессии; session_id уникальны.
- Ни одной паузы длиннее тридцати минут внутри сессии и ни одной пары соседних
визитов куки, разделённой меньшим промежутком.
- Повтор после DROP PARTITION ALL: те же session_id и то же содержимое строк.
- Снесённая руками партиция 2026-06-04: следующий прогон взял хвост от неё,
дни до дыры не тронуты.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Зачем:
- Полный разбор урока про идемпотентность стоял дважды, предупреждение про
окно 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>
Зачем:
- Дать слою первую физическую сущность и показать идемпотентность, устроенную
иначе, чем в приёме: заменой партиции, а не колонкой версии.
- Родить механику дневной пересборки на кластере — образец для сессий и витрин.
Что:
- Добавлены 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>