feat(airflow): пробные DAG test_clickhouse и test_kafka вместо демонстрационного #19

Merged
ddmitry merged 4 commits from feat/18-dag-probes into main 2026-07-31 15:26:38 +03:00
Owner

Закрывает #18 (закрыть вручную: Gitea не понимает русские ключевые слова).

Что сделано

Демонстрационный DAG example_clickstream_hello заменён двумя пробниками,
которые проверяют связи по-настоящему.

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

Вторым коммитом — две находки приёмки, не относящиеся к пробникам:

  • tests/docs-guards.sh теперь называет непрошедшую проверку (раньше падал
    через set -e молча) и объясняет в комментариях, зачем существует каждая;
  • make smoke-cluster больше не виснет: clickhouse-client у запроса INSERT
    дочитывал данные из стандартного ввода и ждал его конца, а при запуске из
    фонового процесса конец не наступал никогда;
  • README получил раздел «Какую проверку когда запускать» — лесенка от дешёвой
    статической проверки к дорогой интеграционной.

Проверка

Приёмочный прогон на чистых томах:

  • make config-test — пройдено 3, 3 и 6, ошибок 0;
  • make clean, cp .env.example .env, make up — 116 с;
  • make smoke — пройдено 25, ошибок 0; стенд занимает 2244,0 MiB при пороге
    3,4 ГБ;
  • make smoke-cluster — все 8 проверок, 7 с.

Фальсификация сторожа документации: сломанный порт в README и разорванная
строка про перезапуск ClickHouse дают красный с именем непрошедшей проверки.

Процесс

Реализация — Codex, самопроверка 3/2. Два слепых ревью разных родословных:
по коду — APPROVED, по задаче — 8 находок. После триажа и перепроверки
мутациями всплыли ещё две; все десять закрыты.

Третьим коммитом — вывод из этого же прогона

AGENTS.md получил правило выбора исполнителя. Пробники написаны технически
безупречно и при этом неправильной формы: монолитная задача в DAG, ручная
машинерия уборки там, где у Airflow есть trigger_rule, ноль комментариев к
самому неочевидному решению репозитория — чтению ноды 2 через remote().
Двадцать критериев тикета закрыты все двадцать, и это ничему не помогло.

Раз учебная ценность записана как базовая, читатель — не побочный потребитель,
а тот, ради кого стенд существует. Значит вкусовую работу пишет модель с
чувством меры, техническую — Кодекс, а разрез намечается по подзадачам при
планировании. Правка процессная, к пробникам прямого отношения не имеет;
вынести её отдельным PR, если так чище.

Закрывает #18 (закрыть вручную: Gitea не понимает русские ключевые слова). ## Что сделано Демонстрационный DAG `example_clickstream_hello` заменён двумя пробниками, которые проверяют связи по-настоящему. - **`test_clickhouse`** пишет строку в `ReplicatedMergeTree` на ноде 1 и читает её с ноды 2 через `Distributed`. Данные проходят путь «нода 2 → все шарды → шард ноды 1»: проверяется межшардовое чтение, а не доступность одной ноды. - **`test_kafka`** пишет в постоянный топик сообщение с меткой прогона и вычитывает его обратно. - **Образ.** `clickhouse-connect` 1.6.0 и `confluent-kafka` 2.15.0 вшиты в `infra/airflow/Dockerfile`, импорт проверяется на сборке: при запуске контейнера пакеты не доустанавливаются. - **Проверки.** `make smoke` гоняет оба пробника через API Airflow (25 проверок), `make config-test` разбирает DAG без стенда, `tests/stand-smoke-guards.sh` проверяет красный путь, `tests/dag-probes-unit.py` — модульные проверки разбора. Вторым коммитом — две находки приёмки, не относящиеся к пробникам: - `tests/docs-guards.sh` теперь называет непрошедшую проверку (раньше падал через `set -e` молча) и объясняет в комментариях, зачем существует каждая; - `make smoke-cluster` больше не виснет: `clickhouse-client` у запроса INSERT дочитывал данные из стандартного ввода и ждал его конца, а при запуске из фонового процесса конец не наступал никогда; - README получил раздел «Какую проверку когда запускать» — лесенка от дешёвой статической проверки к дорогой интеграционной. ## Проверка Приёмочный прогон на чистых томах: - `make config-test` — пройдено 3, 3 и 6, ошибок 0; - `make clean`, `cp .env.example .env`, `make up` — 116 с; - `make smoke` — пройдено 25, ошибок 0; стенд занимает 2244,0 MiB при пороге 3,4 ГБ; - `make smoke-cluster` — все 8 проверок, 7 с. Фальсификация сторожа документации: сломанный порт в README и разорванная строка про перезапуск ClickHouse дают красный с именем непрошедшей проверки. ## Процесс Реализация — Codex, самопроверка 3/2. Два слепых ревью разных родословных: по коду — APPROVED, по задаче — 8 находок. После триажа и перепроверки мутациями всплыли ещё две; все десять закрыты. ## Третьим коммитом — вывод из этого же прогона `AGENTS.md` получил правило выбора исполнителя. Пробники написаны технически безупречно и при этом неправильной формы: монолитная задача в DAG, ручная машинерия уборки там, где у Airflow есть `trigger_rule`, ноль комментариев к самому неочевидному решению репозитория — чтению ноды 2 через `remote()`. Двадцать критериев тикета закрыты все двадцать, и это ничему не помогло. Раз учебная ценность записана как базовая, читатель — не побочный потребитель, а тот, ради кого стенд существует. Значит вкусовую работу пишет модель с чувством меры, техническую — Кодекс, а разрез намечается по подзадачам при планировании. Правка процессная, к пробникам прямого отношения не имеет; вынести её отдельным PR, если так чище.
ddmitry added 3 commits 2026-07-31 14:10:23 +03:00
- Зачем:
  - инженерные скиллы (to-tickets, triage, wayfinder, domain-modeling) ждут
    репо-локальную настройку; без неё они не знают, чем заводить issues и
    какими метками размечать. Дока трекера жила ссылкой на репозиторий
    предшественника — внешняя зависимость на месте источника истины.
- Что:
  - заведён docs/agents/: issue-tracker.md (Gitea через tea, команды,
    wayfinding, отдельный раздел про то, что «Закрывает #NN» issue не
    закрывает), triage-labels.md (пять канонических меток без переименований)
    и domain.md (один контекст, CONTEXT.md и docs/adr/).
  - в AGENTS.md добавлен раздел «Agent skills» со ссылками на эти файлы,
    ссылка на доку предшественника заменена локальной.
  - в «Структуре» закреплён нейминг: ГГГГ-ММ-ДД-слаг для docs/specs/ и
    docs/research/, NNNN-слаг для docs/adr/.
- Проверка:
  - tea labels list — все пять меток триажа заведены в репозитории;
  - tea api version — Gitea 1.27.0, команды из доки отвечают живьём.
Зачем.
Демонстрационный 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>
Зачем.
Сторож `tests/docs-guards.sh` падал через `set -e`: единственным следом была
единица в коде возврата, а какое именно утверждение о README перестало быть
правдой — не сообщалось. Со стороны файл выглядел набором несвязанных grep
без объяснения, зачем каждый из них нужен.

Отдельно: `make smoke-cluster` мог зависнуть навсегда. У запроса INSERT
clickhouse-client дочитывает данные из стандартного ввода и ждёт его конца;
при запуске не из терминала, а из фонового процесса с открытым вводом конец
не наступает никогда. Проверка молча висела больше двадцати минут.

Что.
- Проверки собраны в именованные функции, каждая с комментарием, зачем она
  существует и что ломается, когда она краснеет.
- Обёртка `check` печатает утверждение и при успехе, и при провале, считает
  пройденные и выходит с понятным сообщением.
- Ввод запросов ClickHouse закрыт через `</dev/null`, рядом — объяснение
  причины.
- README: раздел «Какую проверку когда запускать» — лесенка от дешёвой
  статической проверки к дорогой интеграционной, с ответом, зачем внутри
  `make smoke-guards` три прогона `make smoke`.

Проверка.
make config-test — пройдено 3, 3 и 6, ошибок 0.
Фальсификация сторожа: порт ноды 2 в README изменён — «ОШИБКА: не
подтвердилось: README перечисляет HTTP- и нативные порты обеих нод», код 1;
двоеточие в строке про перезапуск ClickHouse заменено на тире — «ОШИБКА: не
подтвердилось: README требует перезапуск ClickHouse после изменения настройки
метрик», код 1. README восстановлен из индекса.
make smoke-cluster с открытым стандартным вводом — 8 проверок за 7 с; до
починки та же команда висела 23 минуты и была снята вручную.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ddmitry added 1 commit 2026-07-31 15:23:06 +03:00
Зачем.
Учебная ценность записана как базовая, но вывода о выборе исполнителя из
неё не делалось. Прогон #18 показал цену пропуска: код технически
безупречен и при этом неправильной формы — монолитная задача в DAG, ручная
машинерия там, где у Airflow есть свой механизм, ноль комментариев к самому
неочевидному решению.

Что.
В «Цель репозитория» добавлено правило: всё, что человек будет читать и
разбирать, пишет модель с чувством меры; техническая работа без вкусовых
решений — Кодексу; линии ревью всегда разных родословных. Отдельно
отмечено, что экономия лимитов на читаемом коде ложная.

Проверка.
make config-test — пройдено 3, 3 и 6, ошибок 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ddmitry merged commit 8d9acc8eb0 into main 2026-07-31 15:26:38 +03:00
ddmitry deleted branch feat/18-dag-probes 2026-07-31 15:26:39 +03:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ddmitry/clickstream-data-platform#19