Commit Graph
230 Commits
Author SHA1 Message Date
ddadmin 39ff0b5bb4 feat(dds): добавлена карта идентичностей
- Зачем:
  - реализованы требования issue #153 к мосту между кукой и пользователем.
- Что:
  - добавлены физическая карта, точное представление и полный пересчёт через GLOBAL JOIN.
  - задача identity_map поставлена после сборки заказов в dds_transform.
  - устройство и живые проверки карты записаны в документации хранилища.
- Проверка:
  - make lint, make smoke, make check-clickhouse, make check-services.
  - три запуска dds_transform: 4770 физических строк и 1590 уникальных пар в _v.
2026-08-26 12:30:40 -04:00
ddmitry cdd44c469f Merge pull request 'feat(ods): версией заказа стала дата слепка, окно DDS — из данных' (#167) from 165-ods-order-version-snapshot-date into main
Reviewed-on: #167
2026-08-26 18:50:37 +03:00
ddadmin a9cead2974 docs(orders): документация перестроена вокруг текущей модели
- Зачем:
  - описание вело нового читателя через историю исправления вместо действующего
    контракта слоёв.
- Что:
  - прямо описаны версия заказа, границы пакетного приёма и расчёт окна DDS.
  - ответственность ODS, DDS и конвейера разделена без ссылок на прежние
    ошибки как на основной довод.
  - исторический вывод исследования помечен до устаревшего абзаца, а ссылки
    ведут к отдельным решениям и контрактам.
- Проверка:
  - make lint.
  - make config-test.
2026-08-26 18:47:22 +03:00
ddadminandClaude Opus 5 a82c75705d feat(ods): версией заказа стала дата слепка, окно DDS — из данных
- Зачем:
  - ярлык 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>
2026-08-26 17:28:14 +03:00
ddmitry 650efacc3f Merge pull request 'feat(dds): модель сессии и нарезка визитов окнами' (#166) from 152-dds-session-model into main
Reviewed-on: #166
2026-08-26 16:19:06 +03:00
ddadminandClaude Opus 5 176cf5520d feat(dds): добавлена модель сессии и нарезка визитов окнами
Зачем:
- Дать слою расчётную сущность, которой в потоке нет: стенд режет визиты сам,
  а 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>
2026-08-26 07:56:44 -04:00
ddadminandClaude Fable 5 c361c36e3d docs(adr): версия заказа в ODS пересмотрена на дату слепка
- Зачем:
  - лотерея ярлыков доставки при ничьей по updated_at делала слой
    недетерминированным и держала окно K двумя копиями без сверки (#163).
- Что:
  - добавлен ADR 0014: версия ods.order — snapshot_date, с ответом доводу
    ADR 0010, границами допущения и веером отклонённых вариантов.
  - в ADR 0010 помечен пересмотр колонки версии.
- Проверка:
  - реализация и замеры — тикет #165; решение кодом пока не применено.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 06:38:46 -04:00
ddmitry 9ab43e79cc Merge pull request 'feat(dds): модель заказа и пересборка окна заменой партиций' (#164) from 151-dds-order-model into main
Reviewed-on: #164
2026-08-26 12:36:09 +03:00
ddadminandClaude Opus 5 535b03783a docs(dds): убраны повторы объяснений в комментариях заказа
Зачем:
- Полный разбор урока про идемпотентность стоял дважды, предупреждение про
  окно 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>
2026-08-26 05:32:03 -04:00
ddadminandClaude Opus 5 1e8b83ffbb 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>
2026-08-26 05:20:39 -04:00
ddmitry 96829718f9 Merge pull request 'docs(dds): уточнён публичный контракт события' (#162) from 150-dds-event-review-fixes into main 2026-08-26 00:54:21 +03:00
ddadmin ae5bd31dbd docs(dds): уточнён публичный контракт события
- Зачем:
  - Закрепить реалистичную границу доступа BI и убрать двусмысленность для неизвестных кодов.
- Что:
  - Пояснены доступ к ODS, пояс счётчика и порядок DDL.
  - Проверка равенства строк отделена от размера конкретной загрузки.
- Проверка:
  - `git diff --check`.
  - `make config-test` не стартовал: Snap требует работающий `snapd.apparmor`.
2026-08-25 17:53:22 -04:00
ddmitry b8a5a6171c Merge pull request 'feat(dds): добавлен публичный контракт события' (#161) from 150-dds-event-contract into main
Reviewed-on: #161
2026-08-26 00:45:37 +03:00
ddadmin 9ea361d199 feat(dds): добавлен публичный контракт события
Зачем:
- Показать слой DDS как договор данных, которому не нужна физическая копия.
- Сохранить простой учебный стенд без отдельного маршрута ради узких прав.

Что:
- Добавлено кластерное представление dds.event_v с явными 44 колонками.
- Роли bi_reader разрешено чтение ODS, DDS и DM при договоре чтения через _v.
- Согласованы мастер-спека, ADR, справочники архитектуры и живые тикеты этапа.
- Зафиксировано исследование поведения DEFINER поверх Distributed.

Проверка:
- make config-test
- make smoke
- make check-clickhouse
- Приёмочные запросы: равенство ODS/DDS, состав колонок, коды устройств и права bi.
2026-08-25 17:13:35 -04:00
ddmitry 4ea9591a16 Merge pull request 'Опись мира: счётчики классов A и C' (#160) from 157-inventory-class-counters into main 2026-08-25 20:13:38 +03:00
ddadminandClaude Fable 5 f45ad53b7f docs(dq): classes_vs_inventory названа технической проверкой
- Зачем:
  - сверка с описью подглядывает внутрь генератора: у настоящего магазина
    такого оракула нет, и выдавать её за учебный урок DQ нельзя (развилка
    из комментария к #157).
- Что:
  - в dm.md проверка счётчиков классов помечена технической, её обещание
    сужено честно: до витрин доехал рождённый мир; верно ли мир рождён,
    проверка не видит — опись считает тот же генератор.
  - в §8 мастер-спеки читатель счётчиков «самопроверка лабы сверки»
    заменён на техническую проверку classes_vs_inventory звена DQ.
  - словарь: короткий термин «Техническая проверка» в CONTEXT.md — только
    язык, решение живёт в dm.md; та же формулировка читателя в inventory.md.
- Проверка:
  - grep -rn "лабы сверки" docs/ — упоминаний не осталось.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 12:47:48 -04:00
ddadmin 1267b45f47 feat(generator): добавлены счётчики классов заказов
Зачем:
- дать описи контрольные числа для закрытых дней заказного окна;
- зафиксировать словарь наблюдаемых классов без изменения самого мира.

Что:
- посчитаны match, cancelled и amount_delta с приоритетом отмены;
- счётчики добавлены только к дням с закрытым окном;
- опись, тесты и документация приведены к новому формату.

Проверка:
- make lint;
- make typecheck;
- make test — 429 passed;
- uv run pytest tests/test_inventory.py -q — 3 passed после ревью.
2026-08-25 11:35:31 -04:00
ddmitry f1fee5f1d1 Merge pull request 'Слой витрин DM: форма по зерну, дележ с менти, контур DQ' (#147) from 135-dm-marts into main
Reviewed-on: #147
2026-08-25 13:38:21 +03:00
ddadminandClaude Fable 5 2f9a26eb0e docs(dm): вычитан слой витрин вторым горячим ревью
- Зачем:
  - после переписывания ритма пересборки в тексте остались швы прежних
    формулировок и один разрыв с докой конвейера.
- Что:
  - довод против дневных партиций daily_traffic заменён верным: партиция —
    единица замены, а витрина заменяется только целиком (число строк тут
    ни при чём, иначе довод бил бы и по dq_summary).
  - в etl.md к механике REPLACE PARTITION добавлена вторая идемпотентность
    конвейера — полная перезапись в ReplacingMergeTree.
  - правило ритмов говорит про день, а не партицию; поправлены переносы
    строк и обороты.
- Проверка:
  - make config-test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 06:37:09 -04:00
ddadminandClaude Fable 5 92d834761c docs(dm): ритм пересборки витрин выведен из подвижности источника
- Зачем:
  - обсуждение горячего ревью показало: «окно K для всех» — ритм заказов,
    натянутый на слой, а замерзание daily_traffic обесценивало витрину.
- Что:
  - раздел «Объём пересборки» заменён «Ритмом пересборки»: три ритма —
    хвост / окно K / целиком; daily_traffic наследует у карты полный
    пересчёт в ReplacingMergeTree, дневные партиции ей не положены.
  - в отклонённые добавлены замерзание за окном K и инкремент по
    first_matched_at; инкремент стал идеей лабы повышенной сложности #149.
- Проверка:
  - make config-test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 06:33:10 -04:00
ddadminandClaude Fable 5 99496971e2 docs(dm): вычитана дока слоя витрин
- Зачем:
  - горячее ревью развилки #135 нашло два незакрытых решения: объём
    пересборки витрин и судьба менти-витрины после постройки.
- Что:
  - добавлен раздел «Объём пересборки»: одно окно K для всех витрин,
    замерзание daily_traffic за окном названо решением с объяснением.
  - в ТЗ менти добавлен финальный пункт — встроить витрину в dm_transform.
  - поправлены мелочи: greenplum-стенд больше не зовётся предшественником,
    добавлены ссылки на спеку и карту идентичностей.
- Проверка:
  - make config-test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 04:57:17 -04:00
ddadminandClaude Fable 5 70a9aeddb7 docs(dm): спроектирован слой витрин DM
- Зачем:
  - развилка #135 карты #127 решена: форма и состав витрин DM,
    контур DQ этапа 4; резолюция переносится в доки architecture.
- Что:
  - создана docs/architecture/dm.md: форма по зерну, дележ витрин
    между стендом и заданиями менти, dq_summary с REPLACE PARTITION,
    звено DQ конвейера и даг самопроверки домашек.
  - ссылки на #135 в etl.md и dds/README.md заменены на доку слоя.
- Проверка:
  - make config-test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 04:40:30 -04:00
ddmitry 70270c2d54 Merge pull request 'Дневной конвейер трансформаций: etl_pipeline рождается этапом 4' (#146) from 134-etl-pipeline into main 2026-08-25 10:26:53 +03:00
ddadminandClaude Fable 5 d1aad3b143 docs(etl): вычитан дневной конвейер
Зачем: горячее ревью доки перед слиянием PR #146.

Что: «единственный на стенде» больше не читается как «единственный даг
стенда»; в пункте про живой день причина порядка триггера названа один раз
и по делу; конвейер дёргает работник живого дня, а не работники; в
ретро-пометке ADR 0009 расставлены кто кого дёргает.

Проверка: перечитка диффа.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 03:25:08 -04:00
ddadminandClaude Fable 5 ebe3de4ae8 docs(etl): спроектирован дневной конвейер трансформаций
Зачем: развилка #134 карты #127 — чем и когда гоняются трансформации DDS
и витрины-таблицы, пока спека числила etl_pipeline за этапом 5.

Что: дока docs/architecture/etl.md — даг etl_pipeline рождается этапом 4:
дёргает dds_transform и dm_transform последовательно (DQ — будущее звено);
живой день зовёт его с ожиданием после установки позиции, после разгона
пачкой менти запускает рукой, world_initialize — последним шагом; параметров
нет, объём выводится из world_position и состояния слоёв; первый шаг —
ожидание хвоста hits; механика REPLACE PARTITION — этап 4, этапу 5 —
партиционная переобработка. Указатели в доках заказа, сессии, README слоя
и ретро-пометки в ADR 0008/0009 переведены на новую доку.

Проверка: вычитка; резолюция и доводы — в тикете #134.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 03:22:35 -04:00
ddadmin f0c4b4c627 docs(dds): зафиксирована физическая модель карты идентичностей
- Зачем:
  - согласованная модель нужна для пакетной реализации DDS и понятного публичного интерфейса слоя.
- Что:
  - описаны физическая карта идентичностей, полный пересчёт и отказ от first_matched_at.
  - унифицирован публичный контракт _v для событий, заказов, сессий и карты.
  - синхронизированы мастер-спека, имена объектов и граница доступа.
- Проверка:
  - git diff --cached --check.
2026-08-24 15:52:17 -04:00
ddmitry 256d51840b Merge pull request 'Контракт dds.event_v: язык модели, расшифровки, скрытые колонки' (#144) from 132-dds-event-contract into main
Reviewed-on: #144
2026-08-24 21:11:59 +03:00
ddadminandClaude Fable 5 7fc12fb8c9 docs(dds): вычитан контракт события
- Зачем:
  - горячее ревью резолюции #132 нашло шероховатости, мешающие читателю.
- Что:
  - срезан дубль про event_date из «Языка модели» — факт живёт в «Форме»,
    расхождений имён осталось два.
  - выровнены префиксы dm. в «Читателях», распутана фраза про два слоя
    DQ-сверки, ссылка на спеку — в домашнем стиле.
- Проверка:
  - вычитка.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 14:09:15 -04:00
ddadminandClaude Fable 5 92ed3011e6 docs(dds): спроектирован контракт dds.event_v — язык модели поверх ODS
- Зачем:
  - развилка #132 карты #127: витринам DM и сборке сессий нужен контракт
    события на языке бизнес-модели, первый пример правила «слой — это
    контракт, а не обязательно копия данных».
- Что:
  - создан docs/architecture/dds/event.md: представление над ods.event_v,
    имена модели (event_id, event_time в поясе счётчика, event_date
    переименованием), расшифровка device_category, скрыты VisitID, Sign,
    ecommerce и служебные колонки.
  - в README карта модели ведёт на event.md, развилка убрана из открытых
    решений; session.md ссылается на резолюцию судьбы VisitID.
- Проверка:
  - вычитка; относительные ссылки в docs/architecture/dds/ ведут на
    существующие файлы.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 14:04:51 -04:00
ddmitry 83f4e0952b Merge pull request 'Модель сессии в DDS: нарезка стендом, эталон VisitID, дневная партиция' (#142) from 131-dds-session-model into main
Reviewed-on: #142
2026-08-24 20:42:03 +03:00
ddadminandClaude Fable 5 4d43b7badd docs(dds): дописаны следствия ключей сессии — локальность и судьба VisitID
Зачем: две находки горячего ревью #131 уровня решения, принятые владельцем.

Что: в «Движок и наполнение» — следствие совпадения ключа шардирования с
событиями: сессионизация локальна по природе, капкан смены ключа у сессий
не стреляет; в «Сверку с эталоном» — зацепка для развилки #132: VisitID
нужен сверке, но не сборке, его дом решает контракт dds.event_v.

Проверка: вычитка; утверждение о локальности сверено с разделом
«Раскладка по шардам» доки хранилища.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 13:40:45 -04:00
ddadminandClaude Fable 5 9237870ab5 docs(dds): вычитана модель сессии
Зачем: горячее ревью резолюции #131 перед мержем PR #142.

Что: поправлена фраза про торговые события (они держат сессию, а не
«рвут»), метка времени названа явно (UTCEventTime), убрано задвоение
про «цели» между составом строки и списком расхождений, у счётной
сверки честно назван предел — взаимная компенсация ошибок внутри
куки за день счёту не видна.

Проверка: повторная вычитка; утверждения сверены с CONTEXT.md, спекой
(разделы 1, 6, 7) и докой хранилища.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 13:37:14 -04:00
ddadminandClaude Fable 5 6f2692737b docs(dds): спроектирована модель сессии — нарезка стендом, эталон VisitID
Зачем: развилка #131 карты #127 — зерно и правила сборки dds.session;
резолюция переносится в доки слоя тем же PR.

Что: дока docs/architecture/dds/session.md — зерно «один визит», нарезка
по правилу визита самим стендом (стенд в роли сессионизатора), session_id
как детерминированный хеш, состав строки по образцу визита Метрики без
денег и целей, MergeTree с заменой дневной партиции, сборка одним дневным
батчем после слепка, счётная DQ-сверка с VisitID (кука × день); в README
слоя сессия переведена из открытых решений в карту модели.

Проверка: вычитка доки; ссылки на разделы спеки и соседние доки сверены
с текстом.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 13:32:49 -04:00
ddmitry 111315990b Merge pull request 'Модель заказа в DDS: зерно, массивы позиций, замена партиций' (#141) from 130-dds-order-model into main
Reviewed-on: #141
2026-08-24 19:09:30 +03:00
ddadminandClaude Fable 5 40de2e5c5f docs(dds): вычитаны модель заказа и карта слоя
- Зачем:
  - горячее ревью после написания: неточности формулировок и один пропуск
    в списке читаемых колонок.
- Что:
  - уточнено, что дом набора выбран развилкой #130, а не «первой развилкой
    карты» (первыми шли research-тикеты);
  - сверке добавлен order_date в перечень читаемых колонок (спека, §7:
    колонка order_day);
  - мастер-спека слинкована при первом упоминании; пояснена роль резолюции
    #128 в «Связанных решениях».
- Проверка:
  - только документы; ссылки сверены с деревом docs/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 12:06:54 -04:00
ddadminandClaude Fable 5 7972847601 docs(dds): спроектирована модель заказа в DDS и заведён набор доков слоя
- Зачем:
  - развилка #130 карты #127: заказу нужен объект в DDS — зерно, состав,
    движок и судьба служебных колонок; резолюции этапа 4 нужен дом в git.
- Что:
  - создан набор docs/architecture/dds/ по ADR 0011: README с картой
    модели и правилами слоя, order.md с моделью заказа — зерно «заказ в
    текущем состоянии», позиции массивами, MergeTree с заменой партиций,
    свои _load_id/_load_ts вместо ярлыков ODS (закрывает наследство #85);
  - указатели на модель добавлены в orders/README.md, orders/ingestion.md
    и storage.md.
- Проверка:
  - только документы; относительные ссылки сверены с деревом docs/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 12:03:26 -04:00
ddmitry 1adacc6d7c Merge pull request 'docs(research): соединение Distributed-таблиц на кластере' (#140) from research/distributed-join into main 2026-08-22 11:42:09 +03:00
ddmitry d359882e1d Merge pull request 'docs(research): проталкивание условий сквозь представления над FINAL' (#139) from research/view-predicate-pushdown into main 2026-08-22 11:42:05 +03:00
ddmitry 544e500dc8 Merge pull request 'Разложить заказы в ODS по своему ключу шардирования' (#138) from 137-orders-shard-colocation into main
Reviewed-on: #138
2026-08-22 11:38:55 +03:00
ddadminandClaude Opus 5 45360b6bcf docs(ods): вычитаны комментарии и документация починки раскладки
- Зачем:
  - правки #137 дважды рассказывали одно и то же: механика капкана жила и в
    storage.md, и у вставок, а цифры замеров — и в прозе, и в леджере;
    у читателя это спрашивает больше внимания, чем даёт.
- Что:
  - комментарии у вставок order_parse.sql сжаты до довода с указателем на
    storage.md; из капкана в storage.md цифры ушли в «Что проверено»;
    в ingestion.md замеры перенесены из прозы в свой раздел «Что проверено».
- Проверка:
  - рендер order_parse.sql по-прежнему делится ровно на два запроса
    (из комментария убрана точка с запятой, по которой оператор делит файл).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 04:35:41 -04:00
ddadminandClaude Opus 5 94a1ffeee2 docs(ods): описана семантика snapshot_date после схлопывания версий
- Зачем:
  - проверка #137 показала: у заказа, не менявшегося несколько дней, версию
    выбирает только updated_at, и какая из одинаковых строк переживёт
    схлопывание — не обещано; snapshot_date выжившей строки означал не то,
    что обещала документация (у 86 заказов стартового мира выжил серединный
    день наблюдения).
- Что:
  - в docs/architecture/orders/ingestion.md записано: snapshot_date, _load_id
    и _load_ts выжившей строки — координаты одного из наблюдений версии, не
    обязательно последнего; допущение «уточнение поднимает updated_at»
    названо допущением с границей применимости.
  - та же оговорка — в комментарии DDL ods.order_rep.
- Проверка:
  - замеры на живом стенде: во всех 3034 парах строк с равным updated_at
    деловые поля совпали побайтово; монотонность updated_at по слепкам —
    без нарушений; ods.order_v сошёлся с эталоном argMax из сырья построчно.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 04:28:51 -04:00
ddadminandClaude Opus 5 8c76a7a0d8 fix(ods): заказы разложены по своему ключу шардирования
- Зачем:
  - заводское parallel_distributed_insert_select = 2 исполняло вставку из
    Distributed в Distributed локально на каждом шарде, минуя ключ цели:
    1189 из 1662 заказов задвоились на обоих шардах, а ReplacingMergeTree
    через границу шарда дубли не схлопывает.
- Что:
  - в обе вставки sql/ods/order_parse.sql добавлено явное
    parallel_distributed_insert_select = 0 с доводом комментарием.
  - в docs/architecture/storage.md описан капкан «INSERT из Distributed в
    Distributed при несовпадающих ключах» и записана проверка (#137).
- Проверка:
  - межшардовые дубли по ods.order_rep дают 0 (было 1189), каждый шард
    держит только свои ключи; uniqExact(order_id) не изменился.
  - после прожитого дага world_next_day новый слепок принят, дублей
    по-прежнему 0.
  - make smoke, make check-clickhouse.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 04:02:52 -04:00
ddadminandClaude Fable 5 f218795472 docs(research): изучено соединение Distributed-таблиц на кластере
Зачем: тикет #129 (карта #127) требовал проверить, где выполняется JOIN
двух Distributed-таблиц, что даёт GLOBAL и как влияет
distributed_product_mode, — от этого зависят сборка dds.identity_map и
витрина сверки purchase_vs_orders_v этапа 4.

Что: заметка docs/research/2026-08-22-distributed-join.md. Ключевое:
GLOBAL рассылает правую часть с инициатора на шарды; режим local молча
даёт неверный ответ без настоящей ко-локации; подзапрос слева переносит
соединение на инициатор; FULL OUTER с голой левой таблицей задваивает
непарные строки правой части. Попутная находка: ко-локация заказов по
cityHash64(order_id) сломана заводским parallel_distributed_insert_select=2
— починка отдельным тикетом.

Проверка: читающие запросы на живом стенде 26.3.17.56 (log_comment
r129-* в system.query_log обеих нод) и документация ClickHouse через
MCP Context7; стенд не менялся, main не тронут.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 03:39:26 -04:00
ddadminandClaude Fable 5 86ee901dd0 docs(research): проверено проталкивание условий сквозь представления над FINAL
Зачем: контракт будущего dds.event_v зависит от того, доезжают ли условия
запроса сквозь цепочку обычных представлений до индексов таблицы с FINAL,
или представление разворачивается целиком и фильтруется потом (#128).

Что: research-заметка с опытами на живом стенде (EXPLAIN indexes/actions,
сверка read_rows по system.query_log) и сверкой с документацией ClickHouse
через MCP Context7. Ответ: условия доезжают сквозь два уровня, включая
переименования и анализируемые выражения; FINAL отключает только
автоматический PREWHERE. Цепочка представлений ODS -> DDS -> DM годится.

Проверка: только читающие запросы, состояние стенда не менялось; вложенное
представление эмулировано подзапросом.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 03:33:55 -04:00
ddmitry ea39982bdd Merge pull request 'Подключить официальный провайдер ClickHouse к Airflow' (#126) from 124-airflow-clickhouse-provider into main
Reviewed-on: #126
2026-08-22 10:06:05 +03:00
ddadmin 20b0666d28 fix(airflow): добавлен повтор запуска DAG после индексации
- Зачем:
  - при холодном старте GET уже видел DAG, пока POST запуска ещё считал его устаревшим.
- Что:
  - точный стартовый ответ 404 повторяется до двадцати раз с паузой три секунды.
  - прочие ответы и сетевые ошибки завершают команду без риска двойного запуска.
  - граница повторов объяснена в коде и документации проверок.
- Проверка:
  - выполнены `bash -n scripts/run-dag.sh`, `make config-test` и изолированные сценарии ответов API.
  - выполнены холодный `make up`, `make lint` и `make smoke` (21/21).
2026-08-22 02:20:01 -04:00
ddadmin 8d82679bc1 feat(airflow): подключён официальный провайдер ClickHouse
- Зачем:
  - нужен единый штатный путь исполнения SQL и программных запросов ClickHouse из Airflow.
- Что:
  - добавлен официальный провайдер и подключения типа `clickhouse`.
  - SQL-файлы переданы `SQLExecuteQueryOperator`, а программные запросы — `ClickHouseHook`.
  - разбор заказов собран в одном файле, DDL разделён по задачам, документация и смоук обновлены.
- Проверка:
  - выполнены `make lint` и `make config-test`.
  - собран образ, выполнены `pip check`, `make rebuild-storage`, `make smoke` (21/21), `make check-clickhouse` (10/10) и `make check-services` (7/7).
2026-08-22 01:40:56 -04:00
ddmitry 587e392220 Merge pull request 'Передать жизненный цикл мира Airflow' (#125) from 119-world-lifecycle into main
Reviewed-on: #125
2026-08-21 23:55:50 +03:00
ddadmin bca1ffa379 fix(world): устранены расхождения после переноса на main
- Зачем:
  - свежий main добавил мониторинг и проявил устаревшие доводы, мёртвые настройки и слишком короткий тайм-аут DDL.
- Что:
  - документация приведена к текущему жизненному циклу мира и составу стенда;
  - удалены лишняя проверка и неиспользуемый YAML-якорь;
  - ожидание ClickHouse возвращено к 300 секундам, а отказы и параметры DockerOperator пояснены.
- Проверка:
  - `make config-test`;
  - `make lint`;
  - `make smoke` — 21/21.
2026-08-21 23:38:45 +03:00
ddadmin 7e6554507a docs(world): описан жизненный цикл прикладного мира
- Зачем:
  - границы владения Compose и Airflow должны быть видны менти из одного источника истины.
- Что:
  - добавлены спека и ADR жизненного цикла мира;
  - обновлены README, архитектурные справочники и прежние решения;
  - правило полной очистки записано как явное и проверяемое требование к агенту.
- Проверка:
  - документация вычитана через `ai-text-lint` и `writing-for-agents`;
  - выполнена литературная вычитка русского текста;
  - `git diff --check`.
2026-08-21 23:02:15 +03:00