refactor(smoke): цели проверки по назначению — смоук, ClickHouse, службы
- Зачем:
- смоук перестал быть быстрым: 42 секунды из 48 съедали шесть проверок,
которые ждут службу — запуск DAG, вход в Superset, Kafka с машины.
- имена целей врали: смоуком звались и глубокая проверка кластера, и
интеграционные проверки; префикс достался им от общего происхождения.
- нигде не было записано, зачем в репозитории каждая цель и куда класть
новую проверку, — без записи скрипт дорастёт снова.
- Что:
- ось деления — кого спрашивают, а не сколько стоит: make smoke (стенд
собран), make check-clickhouse (спрашивают у ClickHouse), новая
make check-services (службы работают).
- шесть тяжёлых проверок переехали в scripts/stand-services.sh; общее —
счёт, обращение к Compose, зависимости машины и check_containers_survived
— вынесено в scripts/stand-common.sh, копипасты нет.
- smoke-cluster переименована в check-clickhouse; имя файла скрипта не
тронуто (в него встраивается проверка договора со схемой), расхождение
названо в карте.
- смоук и check-services печатают своё время в строке ИТОГ; порога по
времени нет — по доводу ADR 0004.
- docs/architecture/testing.md: карта всех семи целей, правило быстрого
смоука словами, лесенка по частоте и правило про краснеющую проверку,
переехавшее из README; указатель из AGENTS.md.
- README: описания целей сокращены, карта не дублируется; быстрый старт
показывает работающий стенд, а не только собранный.
- планка приёмки этапа в спеке названа поимённо: три цели вместо
«smoke-проверки».
- Проверка:
- make config-test, make smoke (19 проверок, 6 с), make check-clickhouse
(8 проверок, 7 с), make check-services (7 проверок, 44 с) — зелёные.
- 19 + 7 = 25 разных проверок, как и до деления: check_containers_survived
считается дважды намеренно.
- краснеют обе разделённые цели: со снятым prometheus смоук дал три ошибки,
с подменённым UUID подключения Superset покраснел check-services.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
# Проверки: карта целей
|
||||
|
||||
Документ отвечает на два вопроса. Первый: что именно утверждает каждая цель
|
||||
`make` и сколько стоит её прогон. Второй, ради которого документ и заведён:
|
||||
куда положить новую проверку — так, чтобы это решалось по карте, а не чтением
|
||||
скриптов.
|
||||
|
||||
Зона ответственности у документа одна — проверки. Что именно они стерегут,
|
||||
описано в других местах: устройство хранилища — в
|
||||
[storage.md](storage.md), замысел стенда — в спеке [«Боевой реализм стенда
|
||||
(v2)»](../specs/2026-07-30-stand-v2-realism.md).
|
||||
|
||||
## Ось: кого спрашивают
|
||||
|
||||
Цели различаются не ценой, а тем, к кому обращён вопрос. ClickHouse отвечает
|
||||
сам и за миллисекунды. Airflow отвечает через такт планировщика. Superset —
|
||||
через сессию и обход метаданных. Быстрота выходит следствием этого различия, а
|
||||
не критерием деления.
|
||||
|
||||
Совпадение цены и назначения здесь побочное, и это видно по дырам, которые
|
||||
каждая цель оставляет соседке. `make smoke` не заметит перепутанных местами
|
||||
макросов `shard`: обе ноды здоровы и порты отвечают. `make check-clickhouse` не
|
||||
заметит потерянного подключения Superset: он про ClickHouse и только.
|
||||
|
||||
Отсюда правило для новой проверки: **спроси, кого она спрашивает.** Договор со
|
||||
схемой событий — вопрос к ClickHouse, значит дом ему в `check-clickhouse`, даже
|
||||
если по цене он подошёл бы смоуку. Счётчики против манифеста — тоже вопрос к
|
||||
ClickHouse: строки в `ods.event` считает сам сервер и отвечает сразу.
|
||||
|
||||
## Карта целей
|
||||
|
||||
Стенд нужен трём целям из семи. Цена — замер 6 августа 2026 года, см. «Что
|
||||
проверено».
|
||||
|
||||
| Цель | Что утверждает | Стенд | Цена |
|
||||
|---|---|---|---|
|
||||
| `make lint` | Код генератора отформатирован и проходит ruff | не нужен | 0,4 с |
|
||||
| `make typecheck` | Типы генератора сходятся (ty) | не нужен | 0,5 с |
|
||||
| `make test` | Генератор делает то, что обещает; схема события остаётся объявленным контрактом, а собранное из неё [описание выгрузки](../formats/clickstream-event.md) — свежим | не нужен | 40 с |
|
||||
| `make config-test` | Compose разбирается, Bash и Python синтаксически целы, в diff нет пробельных ошибок. О работоспособности не говорит ничего | не нужен | 1 с |
|
||||
| `make smoke` | Стенд **собран**: службы живы, порты отвечают, подключения настроены друг на друга. Вширь и по касательной к каждой службе. Единственная цель, которая здесь правда смоук | нужен | 6 с |
|
||||
| `make check-clickhouse` | Всё, что спрашивают **у ClickHouse** и он отвечает сам: макросы, шарды, реплики, путь в keeper, ключ шардирования, очередь распределённых DDL | нужен | 7 с |
|
||||
| `make check-services` | **Службы работают**: DAG запускается и доходит, топик создаётся и удаляется, Superset логинится и ходит в базу | нужен | 44 с |
|
||||
|
||||
## Правило: смоук обязан оставаться быстрым
|
||||
|
||||
`make smoke` — быстрая проверка для регулярного прогона: её гоняют не
|
||||
задумываясь, и потому она обязана укладываться в секунды. Тяжёлые проверки в
|
||||
неё включать не следует: тяжёлая — та, из-за которой смоук перестаёт быть
|
||||
быстрым. Поодиночке это единицы и десятки секунд, вместе — минуты. Такие
|
||||
проверки живут в `make check-services`.
|
||||
|
||||
На практике дорого обходится не работа, а ожидание службы: такт планировщика
|
||||
Airflow, сессия Superset. `make check-clickhouse` создаёт таблицы, вставляет
|
||||
строки и гоняет распределённые DDL — и укладывается в семь секунд, потому что
|
||||
ClickHouse отвечает сразу.
|
||||
|
||||
Первый абзац — правило, второй — наблюдение, по которому тяжёлую проверку
|
||||
узнают заранее, не замеряя.
|
||||
|
||||
## Какую проверку когда запускать
|
||||
|
||||
Деление целей ценно ровно до тех пор, пока оно не превратилось в «гонять
|
||||
всегда всё».
|
||||
|
||||
| Когда | Что гонять |
|
||||
|---|---|
|
||||
| Правка в работе | `make config-test` и `make smoke` |
|
||||
| PR или задача | плюс цели, которых правка касалась: DAG-и, Superset или Kafka — `check-services`; DDL, кластер или данные — `check-clickhouse` |
|
||||
| Приёмка этапа | `make up` с нуля и все три цели на стенде |
|
||||
|
||||
Правки генератора добавляют к этому `make lint`, `make typecheck` и
|
||||
`make test`: стенд им не нужен, а `make test` из них самая дорогая.
|
||||
|
||||
## Порогов по времени здесь нет
|
||||
|
||||
Цена в таблице — замеренное число с датой замера, а не назначенный порог.
|
||||
Автоматической проверки времени в репозитории нет и заводить её не следует.
|
||||
Число, вписанное в проверку, становится законом, которого никто не выбирал:
|
||||
[ADR 0004](../adr/0004-resource-limits.md) разбирает ровно этот случай — оценка
|
||||
из спеки попала жёстким порогом в `make smoke`, `make smoke` стал критерием
|
||||
приёмки каждого этапа, и дальше решения сверялись уже с порогом, а не с
|
||||
исходным доводом. Спека генератора формулирует ту же позицию прямо:
|
||||
«наблюдаемость без порогов».
|
||||
|
||||
Смотрит на время человек. `make smoke` и `make check-services` печатают его
|
||||
сами — последней строкой `ИТОГ: пройдено N, ошибок M, время T с`. Замер при
|
||||
приёмке делается руками и называется в теле PR.
|
||||
|
||||
## Проверка, которая не умеет краснеть, бесполезна
|
||||
|
||||
Правило, которое стоит держать в голове, правя любую проверку. Проверка,
|
||||
никогда не видевшая своей поломки, доказывает только то, что она умеет печатать
|
||||
«ЗЕЛЁНО». Убедиться дешевле всего руками: сломайте то, что она стережёт —
|
||||
остановите `prometheus`, удалите служебную таблицу пробника на второй ноде, — и
|
||||
посмотрите, покраснеет ли прогон и назовёт ли виновника. Не покраснел —
|
||||
проверка не работает, и чинить надо её, а не стенд.
|
||||
|
||||
## Устройство скриптов
|
||||
|
||||
| Цель | Скрипт |
|
||||
|---|---|
|
||||
| `make config-test` | `scripts/config-test.sh` |
|
||||
| `make smoke` | `scripts/stand-smoke.sh` |
|
||||
| `make check-services` | `scripts/stand-services.sh` |
|
||||
| `make check-clickhouse` | `scripts/clickhouse-smoke.sh` |
|
||||
|
||||
Имя `clickhouse-smoke.sh` осталось от прежнего имени цели — `smoke-cluster`.
|
||||
Файл переименуют при следующем касании: сейчас в него встраивается проверка
|
||||
договора со схемой, и переименование устроило бы конфликт на ровном месте.
|
||||
|
||||
Общее у смоука и `check-services` — счёт проверок, обращение к Compose и две
|
||||
проверки — вынесено в `scripts/stand-common.sh`; сам он не запускается.
|
||||
Оттуда же приходят два решения, которые видно по счёту прогонов:
|
||||
|
||||
- **`check_containers_survived` стоит в конце обеих целей.** Убитый за память
|
||||
контейнер Docker поднимает сам, и проверка здоровья об этом промолчит
|
||||
(ADR 0004). Стенд нагружает `check-services`, а увидеть последствия нужно и
|
||||
тому, кто гонял один смоук. Это единственная проверка, которая считается
|
||||
дважды: 19 у смоука плюс 7 у `check-services` — это 25 разных проверок.
|
||||
- **Зависимости машины считает только смоук.** «На машине есть Docker, curl и
|
||||
jq» — вопрос к машине, а не к службам, и на оси он стоит рядом с «стенд
|
||||
собран». Для `check-services` это условие запуска: без них он не начнёт
|
||||
работу и громко скажет об этом, но ЗЕЛЁНО за это не печатает.
|
||||
|
||||
Вход в Airflow `check-services` выполняет заново — общих переменных у двух
|
||||
скриптов нет. Отдельной проверкой этот вход тоже не считается: то же самое
|
||||
утверждает смоук.
|
||||
|
||||
## Что проверено
|
||||
|
||||
Замеры 6 августа 2026 года, стенд поднят заранее; время `make up` в цену целей
|
||||
не входит. Время взято по `time` и совпадает с тем, что цель печатает сама. Оно
|
||||
плавает от прогона к прогону: смоук дал 5 и 6 секунд, `check-services` — 43 и
|
||||
44. В таблице стоит большее из замеренных.
|
||||
|
||||
До деления `scripts/stand-smoke.sh` шёл 48 секунд на 25 проверок, из них
|
||||
42 секунды съедали шесть: Kafka с машины, два запуска пробников Airflow и три
|
||||
проверки Superset. После деления те же 25 проверок разошлись по двум целям:
|
||||
19 в смоуке и 6 в `check-services`. Содержание ни одной из них не менялось.
|
||||
|
||||
Что обе разделённые цели умеют краснеть, проверено руками в тот же день: со
|
||||
снятым `prometheus` смоук дал три ошибки и ненулевой код возврата; с
|
||||
подменённым ожидаемым UUID подключения Superset так же покраснел
|
||||
`check-services`. Обе краснеют и когда на машине не хватает команды из списка
|
||||
зависимостей.
|
||||
|
||||
Семантика счётчиков Docker `OOMKilled` и `RestartCount`, на которой держится
|
||||
`check_containers_survived`, снята отдельными контейнерами и записана в
|
||||
ADR 0004, раздел «Что проверено».
|
||||
@@ -547,8 +547,11 @@ v2 стартует пустым, поэтому объём ниже — это
|
||||
9. Мониторинг и runbook «keeper упал / DDL повис в очереди». Состав дашбордов
|
||||
и границы — ADR 0002.
|
||||
|
||||
Критерий приёмки этапа — честный: `make up` работает и проходят
|
||||
smoke-проверки, а не «дашборд зелёный». Это минимальная планка; свои
|
||||
Критерий приёмки этапа — честный: `make up` работает и проходят все три
|
||||
проверки на стенде — `make smoke`, `make check-clickhouse` и
|
||||
`make check-services`, — а не «дашборд зелёный». Названы они поимённо
|
||||
намеренно: под общим словом «smoke-проверки» планка тихо опустилась бы при
|
||||
следующем делении целей. Это минимальная планка; свои
|
||||
наблюдаемые критерии каждый этап получает при разбиении в /to-tickets. Документация правится в PR этапа
|
||||
(правило AGENTS.md).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user