Files
clickstream-data-platform/tests/docs-guards.sh
T
ddadminandClaude Opus 5 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>
2026-08-01 14:35:36 +03:00

102 lines
5.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Сторож документации.
#
# README устаревает молча: порт поменяли в compose.yaml, а в описании остался
# старый — и это выясняется через месяц, когда кто-то по нему подключается.
# Здесь собраны утверждения README, которые дёшево проверить текстом и дорого
# обнаружить сломанными. Стенд поднимать не нужно; запускается в составе
# `make config-test`.
#
# Чего сторож НЕ делает: он не проверяет, что README понятен или полон. Только
# то, что перечисленные ниже факты не разошлись с кодом.
#
# Добавляя проверку, формулируй утверждение так, как оно должно читаться в
# отчёте: строка печатается и при успехе, и при провале, поэтому по красной
# строке сразу видно, что именно перестало быть правдой.
set -euo pipefail
readonly ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
readonly README="$ROOT_DIR/README.md"
passed=0
fail() {
printf 'ОШИБКА: %s\n' "$1" >&2
exit 1
}
# check «утверждение» команда... — запускает команду и считает результат.
# Успех: «ЗЕЛЁНО: утверждение». Провал: «ОШИБКА: не подтвердилось: утверждение»
# и выход с кодом 1. Раньше проверки падали через `set -e` молча: код возврата
# был единственным следом, и какая именно проверка не прошла — не сообщалось.
check() {
local claim="$1"
shift
if "$@"; then
passed=$((passed + 1))
printf 'ЗЕЛЁНО: %s\n' "$claim"
else
fail "не подтвердилось: $claim"
fi
}
# Порты обеих нод. Ломается ровно тогда, когда порт поменяли в compose.yaml и
# забыли документацию — самая частая причина расхождения.
ports_documented() {
grep -Eq 'нода 1.*28123.*29000' "$README" &&
grep -Eq 'нода 2.*28124.*29001' "$README"
}
# Совет про сброс томов. Пароли Postgres и Grafana применяются при создании
# тома: без `make clean` смена значений в .env ничего не даёт, и человек
# полчаса ищет, почему его не пускает.
clean_advice_present() {
grep -Eq 'После первого запуска.*`make clean`' "$README"
}
# Список портов остаётся единым списком. Совпадение точное намеренно: проверка
# стережёт не сам факт (он проверен выше), а то, что строку не выдернули из
# списка в отдельный абзац при правке соседнего текста.
ports_stay_one_list() {
grep -Fxq -- '- нода 2 — `http://127.0.0.1:28124`, нативный порт `29001`;' "$README"
}
# Состав `make config-test`. Разбор пробников добавлен в него отдельной
# проверкой, и README должен называть её: иначе читатель считает, что дешёвая
# ступень трогает только Compose, и гоняет полный стенд ради того, что видно
# без него. Проверка стоит на двух соседних строках — см. ниже про перенос.
probe_checks_documented() {
awk '
previous == "`make config-test` проверяет Compose, синтаксис Bash и Python, малые проверки" &&
$0 == "логики пробников и пробельные ошибки в diff без запуска стенда." {
found = 1
}
{previous = $0}
END {exit !found}
' "$README"
}
# Урок из предшественника: `make up` не трогает уже созданные контейнеры, и
# после правки настройки метрик серверы молча работают со старой
# конфигурацией. README обязан требовать явный перезапуск. Проверка сверяет
# две соседние строки целиком, а не подстроку: так фразу нельзя незаметно
# разорвать переносом или переписать наполовину.
restart_lesson_present() {
awk '
previous == "После изменения `infra/clickhouse/config.d/prometheus.xml` выполните" &&
$0 == "`docker compose restart clickhouse-01 clickhouse-02`: обычный `make up` не" {
found = 1
}
{previous = $0}
END {exit !found}
' "$README"
}
check 'README перечисляет HTTP- и нативные порты обеих нод' ports_documented
check 'README объясняет сброс томов после смены исходных учётных данных' clean_advice_present
check 'список портов остаётся единым списком' ports_stay_one_list
check 'README перечисляет малые проверки пробников в составе config-test' probe_checks_documented
check 'README требует перезапуск ClickHouse после изменения настройки метрик' restart_lesson_present
printf 'ИТОГ: пройдено %d, ошибок 0\n' "$passed"