fix(world): устранены расхождения после переноса на main

- Зачем:
  - свежий main добавил мониторинг и проявил устаревшие доводы, мёртвые настройки и слишком короткий тайм-аут DDL.
- Что:
  - документация приведена к текущему жизненному циклу мира и составу стенда;
  - удалены лишняя проверка и неиспользуемый YAML-якорь;
  - ожидание ClickHouse возвращено к 300 секундам, а отказы и параметры DockerOperator пояснены.
- Проверка:
  - `make config-test`;
  - `make lint`;
  - `make smoke` — 21/21.
This commit is contained in:
ddadmin committed 2026-08-21 23:38:45 +03:00
1 parent 7e6554507a
commit bca1ffa379
8 files changed
+45 -34

No files matched your search

+2 -2
View File
@@ -69,8 +69,8 @@ make check-services
`superset-init` завершаются с кодом 0. Первый обновляет схему Airflow,
подготавливает администратора и два подключения к `clickhouse-01`. Второй
обновляет Superset, создаёт администратора и импортирует подключение к
`clickhouse-02`.
С нуля подъём занимает около трёх минут, на живом стенде — около минуты.
`clickhouse-02`. На ноутбуке в режиме энергосбережения приёмочный подъём с
пустых томов занял около десяти минут, повторный на живом стенде — около трёх.
`make smoke` за секунды спрашивает, собран ли стенд: зависимости машины,
здоровье контейнеров, устройство keeper, ответ Kafka с машины через отображённый
-4
View File
@@ -46,10 +46,6 @@ x-kafka-target: &kafka-target
<<: *kafka-common
KAFKA_TOPIC: hits
x-orders-kafka-target: &orders-kafka-target
<<: *kafka-common
KAFKA_TOPIC: *orders-topic
x-world-starting-days: &world-starting-days "8"
x-airflow-common: &airflow-common
+9 -2
View File
@@ -56,7 +56,9 @@ def _clickhouse_client():
password=connection.password,
database=connection.schema or "default",
connect_timeout=5,
send_receive_timeout=60,
# `ON CLUSTER` ждёт хосты до 180 с. Транспорт живёт дольше, чтобы
# ClickHouse сам назвал незавершённый хост вместо сетевого тайм-аута.
send_receive_timeout=300,
)
@@ -97,7 +99,10 @@ def _generator(task_id: str, command: list[str]) -> DockerOperator:
"KAFKA_BOOTSTRAP_SERVERS": KAFKA_BOOTSTRAP_SERVERS,
"KAFKA_TOPIC": HITS_TOPIC,
},
# Вывод уже переехал в журнал задачи; завершённый контейнер не нужен.
auto_remove="force",
# Временный путь Airflow существует внутри контейнера, но монтировать
# его пытается хостовый Docker. Генератору этот каталог не нужен.
mount_tmp_dir=False,
)
@@ -260,7 +265,9 @@ def world_initialize():
finally:
client.close()
raise AirflowException(
f"стартовый мир не принят за 300 с: строк {arrived} из {expected}"
f"стартовый мир не принят за 300 с: строк {arrived} из {expected}; "
"проверьте журнал send_initial_events и "
"SELECT * FROM system.kafka_consumers"
)
@task
+6
View File
@@ -10,6 +10,12 @@
обработчик DAG. Triggerer не запускается: в каркасе нет отложенных задач.
Два интеграционных пробника написаны через публичный `airflow.sdk`.
Долгоживущие процессы Airflow зависят от `airflow-init`, а Superset — от
`superset-init`. Это ребро нужно самому `up --wait`: Docker Compose 2.40.3
считает успешно завершившийся одноразовый сервис без зависимого упавшим и
возвращает единицу — поведение проверено при исполнении #37. Зависимость
включает результат подготовки в общий граф ожидания.
Для входа выбран SimpleAuthManager. У него нет команды создания пользователя,
поэтому `airflow-init` записывает пароль администратора из окружения в
JSON-файл отдельного тома `airflow_auth`. Новый именованный том принадлежит
+4 -2
View File
@@ -144,8 +144,10 @@ Keeper — отдельный сервис, системных таблиц у
вышло восемь: четыре таблицы, каждая обеими нодами. Таблиц ошибок среди них
нет, и это правда состояния — частей у них пока не появилось.
- Очередь DDL показала `CREATE MATERIALIZED VIEW ... ON CLUSTER` в состоянии
`Finished` и со временем по каждой ноде: `make generate-batch` поднимает
`clickhouse-init`, и тот заново прогоняет DDL.
`Finished` и со временем по каждой ноде. Новые безопасные записи для показа
оставляет `make check-clickhouse`: цель создаёт и удаляет временные таблицы
`ON CLUSTER`. Канонический DDL появляется в очереди при создании мира дагом
`world_initialize`.
Подписи рядов (`${__field.labels.node}`) и правило, по которому пунктирным
становится только ряд «отведено», сверены по документации Grafana через MCP
+16 -12
View File
@@ -241,22 +241,26 @@ Kafka → STG → ODS, и живёт он в `make check-clickhouse`.
19/2: назвал нездоровый сервис и отсутствие одной из четырёх целей. После
возврата сервиса прогон снова дал 21/21.
**Приёмка #119 21 августа 2026 года.** `make rebuild-storage` через Airflow
прошёл за 3 м 9 с: позиция прошла задачи `-1` → `0` → `8`, топики получили
новые идентификаторы, группы дочитали новые топики без отставания, а ODS принял
401 185 событий без брака и 2 851 актуальный заказ. Повторный `make up` занял
2 м 41 с вместе со штатным повторным запуском служб инициализации;
`world_initialize` завершился за один цикл опроса и оставил счётчики
неизменными. Отдельно
проверены красные отказы `world_initialize` при `-1` и `world_next_day` при
отсутствующей позиции, `0` и `-1`; `lifecycle` отказано в чтении
`system.users`, но разрешено чтение `system.settings`.
После переноса #119 поверх этого состава повторный `make up` сохранил готовый
мир, смоук прошёл 21/21, проверка ClickHouse — 10/10, межсервисная — 7/7.
**Приёмка логики #119 до переноса поверх мониторинга 21 августа 2026 года.**
`make rebuild-storage` через Airflow прошёл за 3 м 9 с: позиция прошла задачи
`-1` → `0` → `8`, топики получили новые идентификаторы, группы дочитали новые
топики без отставания, а ODS принял 401 185 событий без брака и 2 851
актуальный заказ. Задача `build_generator_image` заняла по 1,5 с в двух
прогонах.
Повторный `make up` занял 2 м 41 с вместе со штатным повторным запуском служб
инициализации; `world_initialize` завершился за один цикл опроса и оставил
счётчики неизменными. Отдельно проверены красные отказы `world_initialize` при
`-1` и `world_next_day` при отсутствующей позиции, `0` и `-1`; `lifecycle`
отказано в чтении `system.users`, но разрешено чтение `system.settings`.
Итоговый холодный `make up` из пустых томов занял 9 м 39 с после 25 с на
`make clean`. Даг создал отсутствующую позицию и закончил на `8`; ODS снова
получил 401 185 событий без брака и 2 851 заказ. У `hits` два раздела, у
`orders` один, отставание обеих групп равно нулю. На этом стенде прошли смоук
20/20, проверка ClickHouse 10/10 и межсервисная проверка 7/7.
`orders` один, отставание обеих групп равно нулю. На тогдашнем составе стенда
прошли смоук 20/20, проверка ClickHouse 10/10 и межсервисная проверка 7/7.
Оборванную очистку проверили после записи `world_position=-1`: остановили
первую ноду ClickHouse, и `world_recreate` покраснел на удалении баз. Следующий
+8 -7
View File
@@ -326,10 +326,10 @@
- **Обрыв любого режима — переигровка дня целиком**; дедуп склеивает
повторы: `WatchID` детерминированы, повтор — та же строка для
ReplacingMergeTree.
- **Эталонный снимок при старте стенда — через Kafka, пакетным режимом
проигрывателя.** Отдельный механизм заливки не строится: каждый `make up`
бесплатно прогоняет весь конвейер на настоящих данных, и строгий приём
хранилища проверяет контракт тем же прогоном.
- **Эталонный снимок при создании мира — через Kafka, пакетным режимом
проигрывателя.** Отдельный механизм заливки не строится: `world_initialize`
прогоняет весь конвейер на настоящих данных при первом `make up` и при явном
`make rebuild-storage`. На готовом мире повторный `make up` заливку пропускает.
Оговорка «если заливка уйдёт в десятки минут — вернуться к прямой
загрузке» проверена при фиксации чисел: 14 × 50 тыс. ≈ 700 тыс. событий —
расчётно минута-две, запас есть.
@@ -361,10 +361,11 @@
окном K = 7, дышащая зона и две волны недельной сезонности. Удлинение до
месяца — дешёвый ход (пересборка описи), если понадобится.
- **В git — только опись, снимок не хранится.** Снимок генерируется при
`make up` и при проверках: артефакт — кэш чистой функции, кэш в git не
хранят. Опись несёт паспорт мира, счётчики и хеши по дням; проверки
создании мира и в проверках генератора: артефакт — кэш чистой функции, кэш в
git не хранят. Опись несёт паспорт мира, счётчики и хеши по дням; проверки
«пустой git diff» и «пересгенерируй день N — сравни хеш» живут на ней.
Каждый `make up` — живая демонстрация детерминизма. Честная потеря —
Первый `make up` пустого стенда — живая демонстрация детерминизма; готовый мир
повторный подъём не пересчитывает. Честная потеря —
страховка на случай платформенного бага: раньше менти с расходящимися
байтами мог взять готовый снимок из git, теперь он упрётся в красный чек
описи; смягчение — CI гоняет генерацию на amd64 и arm64.
-5
View File
@@ -62,11 +62,6 @@ jq -e '
["kafka-init", "clickhouse-init", "world-init", "world-snapshots"] |
all(. as $name | $services | has($name) | not)
' >/dev/null <<<"$config_json"
jq -e '
.services.generator as $generator |
((($generator.depends_on // {}) | has("kafka-init")) | not) and
((($generator.depends_on // {}) | has("clickhouse-init")) | not)
' >/dev/null <<<"$config_json"
jq -e '
.services["airflow-scheduler"] as $service |
($service.environment.CLICKHOUSE_LIFECYCLE_PASSWORD | length > 0) and