4165f10cddb6ef814f6b3db24ba226f910f85e94
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
860c88b7f7 |
chore(tests): выкинуты сторожа документации и тест на комментарий
Зачем tests/docs-guards.sh сличал README с образцами текста: одна проверка требовала двух подряд идущих строк дословно, другая — что в отчёте написано «ГБ», а не «GB». Это тесты на вёрстку абзаца, а не на факт: перестановка слов красит их в красный, хотя ничего не сломано. README всё равно предстоит переписать целиком, когда стенд дорастёт до менти, и тогда эти сторожа краснели бы на здоровом изменении. Из той же семьи была проверка в stand-smoke-static.sh, требовавшая, чтобы в scripts/stand-smoke.sh существовал комментарий определённой формулировки. Что - удалён tests/docs-guards.sh и его запуск из цели config-test; - из tests/stand-smoke-static.sh убрана проверка наличия комментария, счётчик итога приведён к двум оставшимся. Оставлены обе содержательные проверки stand-smoke-static.sh: отказ на недоступных compose.yaml и .env.example и то, что скрипт не виснет в сломанном окружении. Ссылка на удалённый файл в ADR 0004 намеренно не правится: там записано, что было сделано в тот день, и подчищать записи решений под сегодняшнее дерево значит перестать им верить. Проверка make config-test — зелено, 5 и 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
a9d66ed74a |
fix(stand): снят несуществующий бюджет памяти, нодам ClickHouse — 4 ГиБ
Зачем Стенд упирался в память ноды ClickHouse: пробник валился на CREATE TABLE ON CLUSTER, вместе с ним краснели make smoke и make smoke-guards. Причина не та, что предполагал #21: дело не в заводских кэшах, а в коробке на гигабайт. Около 550 МиБ RSS праздной ноды — страницы её собственного бинарника, и на работу оставалось около 350 МиБ, которые пробник добирал за сессию. Заодно выяснилось, откуда взялся предел 3,4 ГБ. Это была оценка расхода из спеки, посчитанная по стенду-предшественнику до первой сборки v2 и превращённая в жёсткий порог проверки. Порог стал критерием приёмки каждого этапа и дальше блокировал бы любой рост стенда на этапах 2-9. Что - ADR 0004: бюджета памяти у стенда нет, есть требование к машине — около 8 ГБ, доступных Docker. Ресурсный довод ADR 0001 отозван, сами решения в силе. - Нодам ClickHouse 4 ГиБ вместо гигабайта. Остальные лимиты не тронуты: ни один из них ни разу не сработал, а снять их скопом — то же изменение без свидетельств, каким они были выставлены. - Из make smoke убрана проверка суммарного потребления. Она мерила docker stats вместе со страничным кэшем, то есть отвечала на вопрос «сколько файлов стенд потрогал», и с появлением настоящих данных краснела бы на здоровом стенде. Вместе с ней убрана привязанная к её сообщению проверка docs-guards. - Взамен smoke спрашивает у Docker, не убивало ли ядро долгоживущий контейнер за память и не включалась ли политика перезапуска. Порога у проверки нет: убитый контейнер Docker поднимает сам, и без этого вопроса стенд отрапортует «всё хорошо» о ноде, которая умирала. - README и раздел «Ресурсный бюджет» спеки переписаны с предела на требование к машине; README объясняет менти, что такое «память, доступная Docker». Проверка make config-test; make up; make smoke — 25 из 25; make smoke-cluster — 8 из 8; make smoke-guards — 3 из 3, включая шаг «после восстановления стенд проходит make smoke», который падал 31 июля. На живом стенде с новой коробкой: max_server_memory_usage = 3,60 ГиБ, в журнале ноды «Lowered mark cache size to 2.00 GiB because the system has limited RAM». Семантика счётчиков Docker снята отдельными контейнерами: ручной restart оставляет RestartCount = 0, убийство за память даёт OOMKilled = true и растущий счётчик, убийство не за память OOMKilled не поднимает. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
dd491ebe33 |
refactor(airflow): пробник Kafka разрезан на запись и чтение
Зачем: пробник Kafka — второй и последний пример DAG в стенде, и после #20 единственный, который не показывает, как здесь пишут код. Одним красным квадратом он к тому же не отвечал на вопрос, какая половина круга отказала: брокер не принял маркер или не отдал его обратно. Что: - вместо одной задачи check_round_trip две: write_marker пишет маркер и возвращает адрес записи, read_marker читает по этому адресу и сверяет; - адрес и маркер едут между задачами XCom — именованными полями словаря: XCom проходит через JSON, и кортеж вернулся бы списком; - внутри записи адрес собирается NamedTuple RecordAddress — два соседних целых в сигнатуре переставляются молча; - каждая задача заводит своего клиента и закрывает его сама, поэтому часовые = None и finally с проверками на None ушли; у продюсера закрыть за собой — это flush(): своего close() у него нет, и он же возвращает число недоставленных; - настройки клиентов и все сроки ожидания стали именованными модульными константами; безымянных чисел в телах задач не осталось; - слитное условие доставки разобрано на шесть утверждений, каждое со своим именем и своим текстом ошибки; - успех больше не возвращается из середины цикла: чтение выходит из цикла по сообщению или по крайнему сроку, а сверка идёт после; - шапка файла приведена к форме «Тест проверяет: ...» с абзацем о том, чем тест не является; она же уходит в doc_md; - комментарии стоят ровно в шести местах, где незнакома модель Kafka. Из настроек консьюмера убран session.timeout.ms: он про членство в группе и удары сердца координатору, а пробник назначает себе адрес и в группу не входит — почему его нет, объясняет шапка файла. Поведение не меняется. Сверено по документации confluent-kafka-python через Context7: session.timeout.ms описан как срок сессии группы, flush() возвращает число оставшихся в очереди сообщений. KafkaProbeTests держался за flush_timeouts == [10, 1], то есть за устройство finally, которого больше нет. На его место встали две проверки свойств: продюсер закрыт даже тогда, когда отказала запись, и чтение назначается ровно на тот адрес, который вернул брокер. Тело issue #22 поправлено тем же изменением: там было записано «задача остаётся одна» — это расхождение с тем, о чём договаривались в гриллинге. Проверка: make config-test зелен; make smoke — оба пробника зелены, красной осталась только проверка памяти стенда по причине из #21. Closes #22 |
||
|
|
dc12953cac |
refactor(airflow): пробник ClickHouse разбит на четыре задачи
Зачем: пробник был одной задачей — в интерфейсе Airflow один красный квадрат, а место отказа приходилось искать по журналу. Ручная машинерия проброса и сведения ошибок занимала больше места, чем сама проверка, и читатель продирался через неё раньше, чем понимал, что пробник проверяет. Пробники — единственный образец DAG в стенде, по ним будут писать остальные. Что: test_clickhouse разбит на prepare_tables, write_marker, read_from_node_2 и cleanup_tables; маркер и имя принявшей запись ноды едут между задачами через XCom строками. Снято сведение ошибок: except BaseException, ExceptionGroup, add_note и накопление ошибок в список; клиент каждая задача заводит общим помощником и закрывает в finally. Ноды описаны константой NODES парами «имя для человека — источник для запроса», булев переключатель и параллельные списки подписей ушли. Уборка идёт обычным правилом запуска, а не all_done: состояние запуска Airflow считает по концам графа, и уборка, отработавшая после отказа, покрасила бы в зелёный запуск с упавшей проверкой — решение записано в ADR 0003. Комментарии остались в четырёх местах: чтение ноды 2 через remote(), импорт клиента внутри функции, правило запуска уборки и автосоздание топика в test_kafka. Малые проверки: заглушка task принимает обе формы декоратора, проверка сведения ошибок заменена проверками уборки. Красный путь ищет образец по журналам всех задач последнего запуска, а не в одном самом свежем. Проверка: make config-test, make smoke (25 проверок) и make smoke-guards зелены. Разбитый пробник укладывается в 5 секунд из 120, отведённых run_airflow_probe, — предел не трогаем. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
812b398ce2 |
fix(tests): сторож документации называет непрошедшую проверку, кластерная больше не виснет
Зачем. Сторож `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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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
|