- Зачем:
- развилка #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>
Зачем: две находки горячего ревью #131 уровня решения, принятые владельцем.
Что: в «Движок и наполнение» — следствие совпадения ключа шардирования с
событиями: сессионизация локальна по природе, капкан смены ключа у сессий
не стреляет; в «Сверку с эталоном» — зацепка для развилки #132: VisitID
нужен сверке, но не сборке, его дом решает контракт dds.event_v.
Проверка: вычитка; утверждение о локальности сверено с разделом
«Раскладка по шардам» доки хранилища.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Зачем: горячее ревью резолюции #131 перед мержем PR #142.
Что: поправлена фраза про торговые события (они держат сессию, а не
«рвут»), метка времени названа явно (UTCEventTime), убрано задвоение
про «цели» между составом строки и списком расхождений, у счётной
сверки честно назван предел — взаимная компенсация ошибок внутри
куки за день счёту не видна.
Проверка: повторная вычитка; утверждения сверены с CONTEXT.md, спекой
(разделы 1, 6, 7) и докой хранилища.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Зачем: развилка #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>
- Зачем:
- горячее ревью после написания: неточности формулировок и один пропуск
в списке читаемых колонок.
- Что:
- уточнено, что дом набора выбран развилкой #130, а не «первой развилкой
карты» (первыми шли research-тикеты);
- сверке добавлен order_date в перечень читаемых колонок (спека, §7:
колонка order_day);
- мастер-спека слинкована при первом упоминании; пояснена роль резолюции
#128 в «Связанных решениях».
- Проверка:
- только документы; ссылки сверены с деревом docs/.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Зачем:
- развилка #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>
- Зачем:
- правки #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>
- Зачем:
- проверка #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>
- Зачем:
- заводское 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>
Зачем: тикет #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>
Зачем: контракт будущего 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>
- Зачем:
- при холодном старте GET уже видел DAG, пока POST запуска ещё считал его устаревшим.
- Что:
- точный стартовый ответ 404 повторяется до двадцати раз с паузой три секунды.
- прочие ответы и сетевые ошибки завершают команду без риска двойного запуска.
- граница повторов объяснена в коде и документации проверок.
- Проверка:
- выполнены `bash -n scripts/run-dag.sh`, `make config-test` и изолированные сценарии ответов API.
- выполнены холодный `make up`, `make lint` и `make smoke` (21/21).
- Зачем:
- свежий main добавил мониторинг и проявил устаревшие доводы, мёртвые настройки и слишком короткий тайм-аут DDL.
- Что:
- документация приведена к текущему жизненному циклу мира и составу стенда;
- удалены лишняя проверка и неиспользуемый YAML-якорь;
- ожидание ClickHouse возвращено к 300 секундам, а отказы и параметры DockerOperator пояснены.
- Проверка:
- `make config-test`;
- `make lint`;
- `make smoke` — 21/21.
- Зачем:
- границы владения Compose и Airflow должны быть видны менти из одного источника истины.
- Что:
- добавлены спека и ADR жизненного цикла мира;
- обновлены README, архитектурные справочники и прежние решения;
- правило полной очистки записано как явное и проверяемое требование к агенту.
- Проверка:
- документация вычитана через `ai-text-lint` и `writing-for-agents`;
- выполнена литературная вычитка русского текста;
- `git diff --check`.
- Зачем:
- второй круг ревью нашёл, что текст спорит с собственной приёмкой: окно
держалось доводом «слияния за минуту-две», а замер даёт двадцать секунд;
довод панели ошибок опирался на отказ по памяти, которого ADR 0004 на этом
стенде не обещает.
- Что:
- «Части» сортируются по таблице: сортировка по числу частей разводила две
ноды одной таблицы, как только между ними вставала чужая.
- у «Слияний» столбик шириной в минуту, иначе редкие события выходили
волосяной линией; из заголовка убран «слой» — фильтр отсекает журналы
сервера, а не выбирает слои.
- в cluster.md исправлены довод за окно, ложное «времени в system.parts нет»,
счёт панелей без нод (их две, не одна) и разрешение, в котором снят замер
процессора.
- панель ошибок и её запись в ADR 0002 переписаны под проверенное: отказ на
шарде воспроизведён принудительным пределом памяти.
- из queries.md убран абзац про SELECT 1 — он объяснял пол удалённой панели.
- Проверка:
- make config-test; make smoke 21/21; make check-clickhouse 10/10.
- все десять панелей отвечают через /api/ds/query в окнах на полчаса, час и
шесть часов; шаг столбика слияний проверен отдельным запросом.
- Зачем:
- слияния в верхних строках показывали только журналы самого сервера, а
предел в 15 строк рвал пару нод пополам: панели отвечали не на свой вопрос.
- Что:
- «Слияния» стали столбиками по слоям: журналы сервера отделены, ряды ods и
stg видны своими.
- «Части» показывают все таблицы слоёв целиком, без предела и без обрезанных
пар.
- у «Запросов» убран «Поток запросов» — его пол составляли пробники
состояния; у «Кто спрашивает» убрана лишняя колонка.
- ряд «коробка» назван «отведено» — как в заголовке панели.
- доводы дописаны в cluster.md и queries.md, отступления от ADR 0002
записаны в сам ADR.
- Проверка:
- make config-test; make smoke 21/21; make check-clickhouse 10/10.
- все десять панелей отвечают через /api/ds/query в окнах на полчаса, час и
шесть часов.
- Зачем:
- ADR 0002 обещает три дашборда; собран был один, а симптом инфраструктуры
как следствие решения человека показать было негде.
- Что:
- cluster.json — семь панелей: процессор, память с пределом коробки, диски,
части по таблицам, слияния, keeper, очередь распределённых DDL.
- queries.json — четыре панели поверх system.query_log: тяжёлые запросы,
поток запросов, аппетит по пользователям, ошибки.
- системные таблицы читаются через clusterAllReplicas; очередь DDL — без
обёртки, она живёт в keeper и у обеих нод одна.
- устройство обоих дашбордов записано в docs/architecture/monitoring/,
правило про пороги поднято из data.md в README набора.
- Проверка:
- make config-test; make smoke 21/21; make check-clickhouse 10/10.
- все одиннадцать панелей отвечают через /api/ds/query.
- Зачем:
- «что скребёт Prometheus» — калька со scrape, по-русски звучит коряво;
рядом нашлись ошибка падежа и пара фраз, которые читаются с запинкой.
- Что:
- заголовок набора и раздел названы по-русски: «за чем следит» и «кого
опрашивает Prometheus».
- «Единицы общие — сообщений за интервал» исправлено на именительный падеж.
- разбиты две перегруженные фразы: про место диагностики версий и про то,
что читать на панели сходимости.
- Проверка:
- make config-test.
- Зачем:
- проход на вычитание: каталог дашбордов появился в этом же PR, и абзац
«что здесь есть» стал называть «Данные» второй раз.
- Что:
- вводный абзац отсылает к каталогу, а имя дашборда и состав панелей
остались только в самом каталоге.
- Проверка:
- make config-test.
- Зачем:
- таблица панелей дублировала заголовки из data.json и уже правилась
дважды; заголовок раздела называл запрещённое действие вместо нужного;
довод про отвергнутые способы счёта сходимости стоял в двух местах.
- Что:
- в таблице панелей остались только источники, вопрос панели читается с её
заголовка на экране.
- раздел про чтецов Kafka назван по тому, что панели делают, опасность
kafka_commit_on_select осталась внутри как причина.
- из записи о приёмке убран пересказ довода, замер оставлен.
- Проверка:
- make config-test; make lint.
- Зачем:
- в общем разделе «Что проверено» лежали два разных прогона, пола и
дашборда; следующие дашборды копили бы там осадок.
- Что:
- запись о приёмке дашборда «Данные» перенесена в data.md, в README.md
осталась приёмка самой зоны.
- Проверка:
- make config-test.
- Зачем:
- половина справочника была про один дашборд «Данные», а этап приносит ещё
два дашборда и правила оповещения: описание самой зоны утонуло бы.
- Что:
- заведён набор docs/architecture/monitoring/ по ADR 0011: README.md — зона
и каталог дашбордов, data.md — устройство дашборда «Данные».
- обе входящие ссылки перенацелены: README.md репозитория и ADR 0002.
- Проверка:
- make config-test; ссылки из README.md и ADR 0002 открываются.
- Зачем:
- две линии ревью нашли, что колонки панели брака читаются как
непересекающиеся кучи, «вовремя ли» из ADR 0002 не считается вовсе, а
отказ от ряда «против вчерашнего» нигде не записан рядом с решением.
- Что:
- в панели брака столбец назван «Из них в брак»: брак — часть приехавшего,
а не соседняя куча.
- панель слепка считает паузу после прошлого слепка — это и есть «вовремя
ли» из ADR 0002; пустая пауза у самого раннего слепка держится
обнуляемым типом.
- отказ от ряда «против вчерашнего» записан в ADR 0002 и в monitoring.md с
доводом: сдвиг на модельные сутки прописал бы ускорение мира в JSON.
- в monitoring.md сказано, почему свежесть читает физическую _dist, а не
ods.*_v, и почему панель слепка не знает окна; довод про сломанный JSON
оставлен у кода, а не задвоен в доке.
- README больше не утверждает, что панелей нет.
- у разбора дашбордов убран флаг -e: он обещал утверждение, которого нет.
- Проверка:
- make config-test (краснеет на нарочно сломанном JSON дашборда), make lint,
make smoke 21/21, make check-clickhouse 10/10; все шесть панелей отвечают
через /api/ds/query. Опыты приёмки и их следы — monitoring.md,
«Что проверено».
- Зачем:
- главный дашборд ADR 0002 отвечает на вопрос «с потоком всё в порядке?»;
три его вопроса — свежесть, брак и сходимость — у предшественника не
заданы вовсе, и в этом весь смысл экрана.
- Что:
- добавлен infra/grafana/provisioning/dashboards/data.json: свежесть, поток,
брак, сходимость, отставание чтения из Kafka и дневной слепок заказов;
порогов и цветовых вердиктов на панелях нет.
- в monitoring.md записано устройство дашборда: почему слои у панелей разные
и как считается сходимость — с доводом и двумя отвергнутыми способами.
- make config-test разбирает JSON дашбордов тем же доводом, что и файлы
дагов: сломанный файл Grafana молча оставляет прежнюю версию.
- Проверка:
- make config-test; на живом стенде make smoke 21/21 и make check-clickhouse
10/10; все шесть панелей отвечают через /api/ds/query.
- Зачем:
- подготовлен пол мониторинга для SQL-панелей и метрик отставания Kafka.
- Что:
- добавлены отдельная роль ClickHouse, источник Grafana и Kafka exporter.
- образ Grafana собирается с закреплённым плагином вне тома данных.
- Prometheus, смоук и документация обновлены под четыре цели.
- Проверка:
- make config-test; make lint.
- make smoke; make check-clickhouse; make check-services.
- make -C generator lint typecheck test.
- Зачем:
- дашборды нужны точками наблюдения на приёмке этапов 4-8, а зависимость
у них формально только от этапа 1: «в хвосте» было выбором, не
необходимостью.
- Что:
- раздел 9: дашборды строятся параллельно этапам 4-8, состав не меняется.
- назван хвост этапа: runbook keeper/DDL, system.text_log, правила
оповещения, урок «посмотрели - сломали - вернули».
- записано правило: панели порогов и цветовых вердиктов не несут, красное
и зелёное живёт в проверках.
- Проверка:
- тикеты этапа нарезаны по этому раскрою: #114-#117 под #11.
- Зачем:
- локальные уточнения документации нужно опубликовать без потери слитых изменений #96 и #109.
- Что:
- актуальный `origin/main` объединён с двумя локальными коммитами документации.
- сохранены уточнения применения настроек ClickHouse и границ проектирования заказов.
- Проверка:
- `make config-test`.
- `make lint`.
- Зачем:
- ODS должен показывать сущность заказа, а не способ её доставки слепком.
- Что:
- физические таблицы и представление переведены на имена `order_*`.
- SQL загрузки, DAG и документация приведены к тому же словарю.
- Проверка:
- `make config-test`, `make lint`.
- `make clean && make up`, `make smoke`, `make check-clickhouse`, `make check-services`.
- Зачем:
- свежий стенд должен показывать отставание ночной выгрузки заказов от кликстрима.
- Что:
- после событий генератор отправляет семь слепков дней 0…6 в общий топик orders.
- make up запускает orders_ingest, ограниченно ждёт его завершения и оставляет день 7 первому ходу мира.
- README и карта проверок описывают второй источник и измеренную цену подъёма.
- Проверка:
- make clean && make up; make smoke; make check-clickhouse; make check-services.
- cd generator && make lint && make typecheck && make test.
- Зачем:
- состав полей DDS определяется вместе с моделью, поэтому отдельная задача заранее не нужна.
- Что:
- удалена задача #85 из списка открытых решений по заказам.
- убран устаревший указатель на неё из описания приёма.
- Проверка:
- выполнен `git diff --cached --check`.
- Зачем:
- перезапуск мог оставить прежнее окружение и старый inode файла, а документы обещали неподдерживаемое живое применение.
- Что:
- в README записано пересоздание нод с ожиданием их здоровья.
- ADR 0007 отделяет решение от процедуры и очищен от устаревших обещаний.
- Проверка:
- make config-test.
- git diff --cached --check.
- Зачем:
- слепок D7 содержал отрицательный итог заказа и попадал в брак ODS.
- Что:
- скидка пересчитана от корзины после удаления отсутствующей позиции.
- сериализатор отклоняет отрицательные деньги через ValueError.
- добавлены проверки восьми стартовых дней и обновлена опись мира.
- Проверка:
- make lint, make typecheck и make test в generator/.
- живой world_next_day: 1694 строки приняты, таблица ошибок пуста.
Зачем: ревью в три линии нашло настоящий дефект. Девятая проверка кластера
звала dictGet('dds.products', …) — объекта после переноса не существует, и
make check-clickhouse падал. Промах вырос из недосчёта: упоминания dds.products
я искал с фильтром по расширениям, .sh туда не попал, и в ADR уехало «четыре
упоминания» вместо семи.
Что: проверка переведена на dic.products и сверяет цену, умножив её обратно на
сто, — так утверждается ещё и точность приведения к Decimal. Раздел 3
мастер-спеки и список пользователей README догнали перенос: оба описывали
отменённое устройство. В ADR 0012 добавлено условие пересмотра для дома — для
него его не было, хотя ради дома тикет и заводился; недосчёт записан в
«Что проверено» как урок. Разнобой обозначений сведён: карта таблиц в доке
хранилища перешла на имена баз строчными, таблица мастер-спеки — на заголовок
«Где», зону всюду зовут зоной, а не слоем. Термин «Справочник» переписан без
метафоры и уложен в формат глоссария. Вычтено лишнее: комментарии DDL
сократились вдвое, из ADR 0006 и 0007 убраны самооправдание и дублирующие
абзацы, отраслевой образец получил честную оговорку о непроверяемости.
Проверка: make config-test, make lint, make smoke и make check-clickhouse —
все зелёные, десять проверок кластера из десяти.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Зачем: горячее ревью поймало ошибку в трёх местах сразу. Было записано, что
после правки каталога ноды расходятся до тридцати секунд — число взято из
ширины окна LIFETIME(MIN 60 MAX 90). Ширина тут ни при чём: каждая нода ждёт
правки от нуля до верхней границы окна, фазы у них независимы, поэтому
расходиться они могут почти на все полторы минуты.
Что: исправлены ADR 0012, опорная точка мастер-спеки и комментарий DDL. Заодно
уточнено, что LIFETIME(0) неатомарность не предотвращал, а сжимал до разброса
исполнения SYSTEM RELOAD DICTIONARY ON CLUSTER, и что витрина выручки пока
спроектирована, а не построена.
Проверка: рассуждением, замером не подтверждалось — прежнее число тоже было
выведено, а не измерено. Замер в ADR (116 секунд на окне MIN 60 MAX 120)
относится к другому утверждению: что словарь обновляется сам.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Зачем: каждое утверждение о словаре было записано трижды — в доке хранилища, в
комментариях DDL и в ADR 0012. Правка поведения стоила бы трёх согласованных
правок, а расхождение между копиями обнаружилось бы не сразу. Дока хранилища —
карта, а не пересказ реализации.
Что: раздел «Справочники» сведён к своему уровню — правило принадлежности зоны,
топология на кластере, единицы денег и указатели. Механика (движок, форма пути,
пользователь, окно обновления) осталась только в sql/ddl/05-dic-catalog.sql,
рядом с кодом, который она объясняет. Блок «Что проверено» отправлен к замерам
ADR 0012 вместо их пересказа — так же, как он уже поступает с ADR 0005.
Проверка: минус 30 строк; ссылок на убранный подзаголовок в репозитории нет,
три относительные ссылки нового текста разрешаются в существующие файлы.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Зачем: место словаря в dds было унаследовано от первого объекта, а не решено.
Справочник читают несколько слоёв, а производит его в хранилище ни один —
прописка внутри одного из потребителей приписывала DDS владение, которого у
него нет.
Что: заведена база dic вне цепочки STG → ODS → DDS → DM, dds.products переехал
в dic.products. Под словарём появилась подложка dic.products_file на движке
File — намеренное усложнение ради урока: в бою источник словаря приезжает
процессом, а не лежит файлом у сервера. Источник объявлен формой query и
приводит цену из целых копеек каталога в Decimal(18, 2), как у денег бэкенда.
Обновление — окном LIFETIME(MIN 60 MAX 90) вместо ручной перезагрузки, ценой
заявленной неатомарности между нодами. У словаря свой беспарольный
пользователь dict с единственным правом на чтение dic. Суффикс _file добавлен
в конвенцию имён ADR 0006. Решение, отвергнутые варианты и условия пересмотра
— ADR 0012.
Проверка: make clean && make up на собранном заново стенде — зелено, make smoke
20 проверок и 0 ошибок, make lint чисто. Словарь LOADED со 180 строками, цена
Decimal(18, 2) и точна на копейках: 188990 → 1889.90. Пользователь bi читает
словарь dictGet-ом со второй ноды, analyst — подложку соединением, база dds
пуста. Минимальное право на движок замерено тремя пользователями: достаточно
GRANT FILE ON *.*, хотя отказ называет TABLE ENGINE ON File.
Closes#105
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Зачем:
- витринам нужен общий с генератором каталог, а менти — пример штатного обновления словаря.
- Что:
- каталог смонтирован read-only в обе ноды и создан как dds.products ON CLUSTER.
- роли получили dictGet, а check-clickhouse сверяет ответ под etl с исходным CSV.
- источник, раскладка и явная политика обновления записаны в документации.
- Проверка:
- make up с чистыми томами; make lint; make config-test; make smoke; make check-clickhouse.
- в generator: make lint typecheck test — 427 тестов прошли.
- Зачем:
- преобразования хранилища должны читаться рядом с целевым слоем, а DAG должен показывать оркестрацию.
- Что:
- запросы забора и разбора заказов разложены по каталогам STG и ODS.
- общий контракт провода подключён в обе ветви штатным шаблонизатором Airflow.
- SQL смонтирован во все службы Airflow, а правило раскладки записано в архитектуре.
- Проверка:
- make lint config-test smoke check-services.
- airflow tasks render для pull_batch и parse_batch; airflow tasks test для parse_batch.
- Зачем:
- менти должен различать версию заказа, наблюдение источника и запуск загрузки.
- Что:
- добавлены таблицы версий и брака заказов, а также представление ods.order_v.
- даг orders_ingest дополнен строгим переходом одного среза STG в две цели ODS.
- результаты опытов записаны в документации, дефект генератора вынесен в #102.
- Проверка:
- make lint config-test smoke check-clickhouse check-services.
Зачем:
- связать проигрывание модельных дней с пакетным приёмом заказов
- показать на одном стенде различие потокового push и пакетного pull
Что:
- добавлен топик, Kafka-чтец и реплицированное сырьё заказов
- добавлен даг orders_ingest с одним прямым чтением и идентификатором загрузки
- работники мира отправляют слепок, ждут приём и только затем двигают позицию
- решения, границы отказа и проверки отражены в ADR и архитектурных документах
Проверка:
- make lint
- make config-test
- make smoke
- make check-clickhouse
- make check-services
- Зачем:
- issue #91 требует решать исход и расхождение заказа в день его рождения.
- Что:
- добавлены три исхода, моменты оплаты и отмены и дельта одной позиции.
- обновлены проверки повторяемости и архитектурное описание заказов.
- Проверка:
- cd generator && make lint && make typecheck && make test (418 passed).
- Зачем:
- тикет #90: второй источник должен смотреть на торговую половину дня
глазами бэкенда — заказ есть проекция покупки, а не второе порождение;
учебный результат — два источника согласованы по построению, а не
сверкой.
- Что:
- `commerce` отдаёт вторым выходом покупки дня: номер заказа, корзину,
выручку клиента, промокод и человека за кукой; новых бросков в
подпоток `COMMERCE` не добавилось, события дня не сдвинулись.
- заведена заказная сторона: подпоток `ORDERS` на позиции 2 дерева зерна
(прежнее мёртвое имя `DISCREPANCIES`), ветвление — по дню рождения
заказа; `LATECOMERS` не тронут, его наполнит этап 6.
- новый модуль `orders.py`: деньги заказа целыми копейками —
`items_total` из корзины, `discount` по таблице «код → скидка»
(округление вниз), `delivery` броском по таблице весов на полную длину
дня, `total` = `items_total` − `discount` + `delivery`.
- план состава завёл `person_id` — последним броском когорты, после
паспортов: вторая кука пары повторяет ID своего человека, заказ
показывает его как `user_id`, в событие Метрики он не попадает.
- `world`: окно изменяемости `ORDER_WINDOW_DAYS` = 7 рядом с D0 и поясом,
черновая таблица стоимости доставки.
- слепок дня в тестах сторожит обе половины: заказы сравниваются наравне
с потоком событий.
- доки: имя подпотока заказной стороны и состав денег заказа записаны в
`docs/architecture/orders`, README генератора знает про новый модуль.
- Проверка:
- из `generator/`: make lint, make typecheck, make test (417 тестов);
в корне — make lint.
- опись мира не покраснела: байты восьми дней те же, заказная сторона
события не сдвинула.
Closes#90
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Зачем:
- потребителю ODS нужна точная актуальная версия события без знания о FINAL.
- Что:
- создано ods.event_v над распределённой таблицей событий с FINAL.
- сверка стартового мира переведена на новое представление.
- документация различает физические версии ODS и бизнес-представление DDS.
- Проверка:
- make config-test.
- make check-clickhouse.
Зачем: черновик этапов держал DDS заказа в этапе 3, а принятый набор
docs/architecture/orders/ оставляет модель DDS проектированию этапа 4
(ingestion.md «Не входит», тикет #85 перевешен на #6) — расхождение
всплыло на холодном ревью нарезки этапа (#89).
Что: в разделе 9 этап 3 сужен до STG/ODS и дага приёма, модель DDS
заказа названа работой этапа 4.
Проверка: чтение; нарезка этапа 3 (#90–#96) согласована с этой строкой.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Зачем: датированная спека — событие истории, а устройство компонента — живой
документ; большое полотно плохо грузится и агентом, и человеком (ADR 0011).
Что: вычитание #84 слито с переустройством формы: набор
docs/architecture/orders/ — индекс README и семь файлов по частям устройства
(нарезка по правилу «семь плюс-минус два»); датированные файлы удалены,
ссылки перенацелены, AGENTS.md дополнен правилом подпапки. Приёмка
владельцем #88 пройдена, черновой статус снят из README.
Проверка: холодная сверка миграции свежим тредом — потерь решений нет;
обход относительных ссылок набора — битых нет.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Зачем: решения развилок #70–#74, #80, #81 карты #69 разошлись по резолюциям
тикетов — цельная картина второго источника нужна в одном месте.
Что: черновик спеки заказов docs/specs/2026-08-16-orders.md и спека приёма
docs/specs/2026-08-16-order-ingestion.md; согласующие правки соседних
документов; правки горячего ревью и двух слепых холодных линий — дефекты
сборки закрыты, назван порядок строк внутри слепка.
Проверка: перепроверка находок теми же ревьюерами — ALL_CLOSED.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>