Commit Graph
20 Commits
Author SHA1 Message Date
ddadmin fc5244cc67 feat(world): жизненный цикл передан Airflow
- Зачем:
  - Compose должен поднимать инфраструктуру, а Airflow — владеть прикладным миром.
- Что:
  - добавлены даги создания и пересоздания мира с явными состояниями позиции;
  - цели make переведены на REST API Airflow, старые одноразовые службы удалены;
  - добавлена ограниченная учётная запись ClickHouse для прикладного DDL.
- Проверка:
  - `make lint`, `make config-test`, `bash -n scripts/run-dag.sh infra/airflow/init.sh`;
  - `make lint` и `make typecheck` в `generator/`;
  - холодный `make up`, повторный `make up`, `make rebuild-storage` и сценарий оборванной очистки;
  - `make smoke`, `make check-clickhouse`, `make check-services`.
2026-08-21 23:01:11 +03:00
ddadmin 48bec014cf fix(monitoring): доводы приведены к замерам, пары нод больше не расходятся
- Зачем:
  - второй круг ревью нашёл, что текст спорит с собственной приёмкой: окно
    держалось доводом «слияния за минуту-две», а замер даёт двадцать секунд;
    довод панели ошибок опирался на отказ по памяти, которого 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 в окнах на полчаса, час и
    шесть часов; шаг столбика слияний проверен отдельным запросом.
2026-08-21 15:28:03 -04:00
ddadmin 42075ff9fb fix(monitoring): панели уточнены по ревью, приёмка снята под нагрузкой
- Зачем:
  - слияния в верхних строках показывали только журналы самого сервера, а
    предел в 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 в окнах на полчаса, час и
    шесть часов.
2026-08-21 15:11:21 -04:00
ddadmin 7ffb4606f1 feat(monitoring): собраны дашборды «Кластер» и «Запросы»
- Зачем:
  - 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.
2026-08-21 14:52:58 -04:00
ddadmin f7123f2ad7 fix(monitoring): ряды панелей подписаны своими именами, а не буквой запроса
- Зачем:
  - на живом дашборде видно то, чего не показывает API: при нескольких
    запросах в панели Grafana ставит перед именем ряда его букву — «A события»,
    «B приземлилось в ClickHouse». Читателю панели это шум.
- Что:
  - свежесть и поток собраны одним запросом на панель: два столбца вместо двух
    запросов. У потока это заодно вернуло ряд заказов, который пропадал, когда
    в окне не было ни одного слепка.
  - у сходимости ряды из разных источников слить нельзя, поэтому ряду
    ClickHouse имя задано переопределением поля.
- Проверка:
  - make config-test; на живом стенде подписи прочитаны прямо со страницы
    дашборда: «события», «заказы», «произведено в Kafka», «приземлилось в
    ClickHouse»; все шесть панелей отвечают через /api/ds/query.
2026-08-21 13:28:22 -04:00
ddadmin e5c573bb25 fix(monitoring): панели уточнены по ревью, приёмка снята на стенде
- Зачем:
  - две линии ревью нашли, что колонки панели брака читаются как
    непересекающиеся кучи, «вовремя ли» из 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,
    «Что проверено».
2026-08-21 11:23:05 -04:00
ddadmin 180ef5b94f feat(monitoring): собран дашборд «Данные» из шести панелей
- Зачем:
  - главный дашборд 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.
2026-08-21 11:06:43 -04:00
ddadmin c5dd9c2d34 feat(monitoring): подготовлена основа мониторинга Kafka и ClickHouse
- Зачем:
  - подготовлен пол мониторинга для 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.
2026-08-21 09:56:56 -04:00
ddadminandClaude Opus 5 5cc0ede75a fix(clickhouse): починена проверка словаря, выметены хвосты переноса
Зачем: ревью в три линии нашло настоящий дефект. Девятая проверка кластера
звала 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>
2026-08-20 12:10:03 +03:00
ddadminandClaude Opus 5 abc94ba406 feat(clickhouse): справочники вынесены в зону dic, словарь читает подложку
Зачем: место словаря в 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>
2026-08-20 11:37:26 +03:00
ddadmin 13abc58d98 feat(clickhouse): добавлен словарь товаров из каталога
- Зачем:
  - витринам нужен общий с генератором каталог, а менти — пример штатного обновления словаря.
- Что:
  - каталог смонтирован 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 тестов прошли.
2026-08-19 00:50:14 +03:00
ddadminandClaude Opus 5 292302e161 fix(airflow): правки пульта мира по двум линиям ревью
Зачем: линия дефектов нашла опору на дефект провайдера, линия постановки —
незаписанный ответ на вопрос ADR 0009 и переменную образца, чьё значение на
чужой машине неверно, а узнаёт об этом читатель через двести строк.

Что: `auto_remove` у прогона генератора переведён с `success` на `force`.
Значение `success` тоже убирало контейнер в любом исходе, но случайно —
удаление у провайдера 4.5.7 стоит в `finally` вопреки собственной
документации; `force` то же поведение называет прямо и переживёт починку.
У выключателя назван `catchup=False`: умолчание Airflow 3 то же самое, но
у дага с тиком в 25 минут и `start_date` в январе это первый вопрос
читателя. «Быстрый старт» предупреждает про `DOCKER_GID` — единственное
значение образца, неверное вне этой машины. В образе Airflow записано, что
провайдер docker приходит с базой (4.5.7 к 3.3.0), — это ответ на вопрос,
который ADR 0009 оставил тикету. Список томов планировщика получил ту же
пометку «правя одно, правьте второе», что стоит у числа дней. Проход на
вычитание срезал три комментария, пересказывавших ADR.

Проверка: `make lint`, `make config-test`, `make smoke` (20/0),
`make check-clickhouse` (9/9) — зелёные. Живой пульт на чистом стенде:
снятый с паузы `world_live` сыграл два дня подряд без нажатия (24 м 07 с и
24 м 06 с, пауза между ними 55 секунд), дочерний прогон виден ссылкой из
задачи выключателя; пауза остановила мир на границе суток — тик прошёл,
третьего прогона нет. Контейнер после прогона с `force` не остался.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 13:57:59 +03:00
ddadmin d0f15bea02 fix(clickhouse): устранены замечания ревью модели доступа
- Зачем:
  - документация и конфигурация доступа должны говорить только подтверждённое.
- Что:
  - ADR приведён к результату межшардового замера.
  - объяснены служебный грант и учебный компромисс remote().
  - удалены избыточные профили, README связан с ADR.
- Проверка:
  - make config-test, make lint, make smoke, make check-clickhouse, make check-services.
2026-08-13 11:31:01 +03:00
ddadmin 780b2d0ef9 feat(clickhouse): добавлен пароль служебному default
- Зачем:
  - default должен остаться только учёткой локальных служебных вызовов.
- Что:
  - пароль default подставлен из окружения на обеих нодах.
  - healthcheck и служебные скрипты передают его внутри контейнера.
- Проверка:
  - make config-test, make up, make smoke, make check-clickhouse, make check-services.
2026-08-13 10:23:32 +03:00
ddadmin 62dc618252 feat(clickhouse): приложения переключены на роли
- Зачем:
  - DDL, Airflow и Superset не должны работать с правами default.
- Что:
  - DDL и Airflow переведены на etl, включая явный доступ remote().
  - Superset переведён на bi с паролем из окружения.
  - etl получил право KAFKA, которое ClickHouse 26.3 требует для движка.
- Проверка:
  - make config-test, make lint, make up, make smoke, make check-services.
2026-08-13 10:19:38 +03:00
ddadmin 790f7c1bb7 feat(clickhouse): добавлены роли и межнодовый секрет
- Зачем:
  - менти должен увидеть разделение доступа без состояния в томах.
- Что:
  - пользователи и роли объявлены файлом с паролями из окружения.
  - межшардовые запросы передают пользователя через общий секрет.
  - четыре допущения реализации подтверждены в ADR живыми замерами.
- Проверка:
  - make config-test, make smoke, make check-clickhouse, make check-services.
2026-08-13 10:04:58 +03:00
ddadmin 704c139d5a refactor(compose): отделены локальные настройки от фактов стенда
- Зачем:
  - устранены дублирование значений и тихая подстановка неполной настройки.
- Что:
  - версии образов и внутренняя топология закреплены рядом с местом использования.
  - имя экземпляра, внешние порты, учётные данные и ключи сделаны обязательными настройками .env.
  - быстрый старт, Dockerfile и статическая проверка приведены к новой границе.
- Проверка:
  - make config-test.
  - docker build для образов Airflow и Superset без аргументов.
  - make up; make smoke; make check-clickhouse; make check-services.
2026-08-08 20:50:35 +03:00
ddadminandClaude Opus 5 64f3418378 feat(airflow): пробные DAG test_clickhouse и test_kafka вместо демонстрационного
Зачем.
Демонстрационный DAG example_clickstream_hello ничего не проверял: он не
обращался ни к ClickHouse, ни к Kafka, поэтому его зелёный результат ничего
не говорил о стенде. Пробники проверяют связи по-настоящему — и тем же
клиентом, каким будут ходить рабочие DAG.

Что.
- test_clickhouse: пишет строку в ReplicatedMergeTree на ноде 1 и читает её
  с ноды 2 через Distributed. Данные проходят путь «нода 2 → все шарды →
  шард ноды 1», то есть проверяется межшардовое чтение, а не одна нода.
- test_kafka: пишет в постоянный топик сообщение с меткой прогона и
  вычитывает его обратно.
- infra/airflow/Dockerfile: clickhouse-connect 1.6.0 и confluent-kafka
  2.15.0 вшиты в образ, импорт проверяется на сборке — при запуске
  контейнера пакеты не доустанавливаются.
- Проверки: scripts/stand-smoke.sh гоняет оба пробника через API Airflow,
  scripts/config-test.sh разбирает DAG без стенда,
  tests/stand-smoke-guards.sh проверяет красный путь,
  tests/dag-probes-unit.py — модульные проверки разбора.
- README и ADR 0001 обновлены тем же изменением.
- Удалён dags/example_clickstream_hello.py.

Проверка.
make config-test — пройдено 3, 3 и 6, ошибок 0.
make clean; cp .env.example .env; make up — 116 с на чистых томах.
make smoke — пройдено 25, ошибок 0; стенд занимает 2244,0 MiB.
make smoke-cluster — все 8 проверок кластера.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 14:04:19 +03:00
ddadminandClaude Opus 5 63c42bc068 feat(infra): стенд целиком — Kafka, Airflow 3, Superset и мониторинг одной командой
Зачем: рядом с кластером ClickHouse не хватало остальной платформы, а
поднимать её по кускам — значит каждый раз вспоминать порядок. Теперь
`make up` даёт стенд целиком, а `make smoke` честно отвечает, работает он
или нет.

Что:
- Kafka в режиме KRaft (без ZooKeeper), Postgres под метаданные, Airflow
  3.3 четырьмя сервисами и Superset 6.1 с драйверами ClickHouse;
- мониторинг: Prometheus снимает метрики с обеих нод ClickHouse и keeper,
  Grafana получает подготовленный источник данных;
- подключение Airflow ведёт на ноду 1, подключение Superset — на ноду 2:
  ловушка правильных ошибок, забытый `ON CLUSTER` виден в дашборде сам;
- `scripts/stand-smoke.sh` — сквозная проверка из 24 пунктов: топик в
  Kafka, цели Prometheus, запуск примера DAG через API Airflow, проверка
  подключения Superset и расход памяти против порога 3,4 ГБ;
- `make config-test` — статические ворота: Compose, синтаксис Bash и
  Python, стражи README; стражи smoke проверяют, что отчёт краснеет на
  сломанном стенде и зеленеет после восстановления;
- решения записаны в `docs/adr/0001-stand-services.md`, состав стенда и
  порядок работы — в README.

Проверка: на чистых томах `make clean` → `cp .env.example .env` →
`make up` (1 мин 51 с) → `make smoke` — 24 пройдено, 0 ошибок, 2171 MiB.
Перезапуск `make down` → `make up` → `make smoke` — 24/0. Также зелены
`make config-test` (3/0 и 5/0), `make smoke-cluster` (8/8) и
`make smoke-guards` (3/0 и 3/0).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 08:46:04 +03:00
ddadmin 2f9bb8700e feat(infra): поднят кластер ClickHouse из двух шардов и keeper
- Зачем:
  - этап 1 спеки требует стенд, поднимаемый одной командой; кластер —
    единственный режим, выключателя «без кластера» нет (issue #12).
- Что:
  - compose.yaml: две ноды ClickHouse и отдельный clickhouse-keeper на
    зафиксированном LTS-образе 26.3.17.56, порты только на 127.0.0.1.
  - infra/clickhouse: общее описание кластера, подключение к keeper и
    отдельные макросы shard и replica для каждой ноды.
  - scripts/clickhouse-smoke.sh: восемь проверок ON CLUSTER от описания
    кластера до удаления временных таблиц, вывод по-русски.
  - tests/smoke-guards.sh: три проверки самой smoke-команды —
    ограниченная аварийная очистка, обработка прерывания, окружение keeper.
  - README.md: быстрый старт, роли нод, обоснование выбора версии.
- Проверка:
  - make up && make smoke && make smoke-guards && make clean
2026-07-30 18:53:14 +03:00