feat(stand): make up наполняет стенд стартовым миром, опись сторожит его
Зачем Стенд поднимался пустым, и всякая приёмка следующих этапов начиналась с ручной заливки данных. Теперь `make up` сам приводит стенд к одному и тому же состоянию, а в git лежит то, чем это состояние проверяется. Что - Опись мира `data/world-inventory.json`: паспорт (зерно, версия генератора, хеш каталога) и по строке на каждый из восьми дней — дата, число событий, хеш байтов. Собирается `make inventory`, свежесть сторожит `test_inventory.py` — тем же способом, что свежесть описания выгрузки. - Разовая служба `world-init` вышла из-под профиля и играет в топик восемь дней при каждом подъёме; зависимый у неё — `airflow-init`, иначе `--wait` считает успешно отработавшую службу упавшей. - `scripts/wait-for-world.sh` — вторая половина `make up`: приём асинхронный, поэтому ждать надо доезда до `ods.event`, а не завершения заливки. Ограниченный цикл опроса, не пауза наугад. - Девятая проверка `make check-clickhouse`: подневный счёт событий против описи, рамка по датам стартового мира, счёт через `FINAL`. При расхождении называет, где искать, — в событиях или в браке. - Порог «день ≤ 30 с» снят из спеки генератора в обоих местах: замер дал 1,7 с, порог был выше факта в восемнадцать раз. На его месте — замеры с датой. Раздел 9 спеки закрыт: открытых вопросов не осталось. - Слова: «манифест» стал описью мира, «зерновой мир» — стартовым миром (решение владельца). Оба заведены в словарь CONTEXT.md. Проверка `make clean && make up` с нуля — 2 м 50 с, доехало ровно 401 185 событий. `make check-clickhouse` зелёный (8 с), `make smoke` зелёный (9 с), `make test` — 407 тестов за 71 с, `make lint`, `make typecheck`, `make config-test` зелёные. Что проверка умеет краснеть, снято двумя поломками: снос партиции 2026-06-03 дал диагноз «не доехали до ODS», негодная строка в сырье — «сломан разбор». Строки опыта убраны, день переигран, счёт вернулся. Тест свежести проверен молчаливой правкой цены в каталоге: покраснел. Ссылка: #42
This commit is contained in:
+50
-19
@@ -52,6 +52,28 @@ x-airflow-common: &airflow-common
|
||||
- airflow_logs:/opt/airflow/logs
|
||||
- airflow_auth:/opt/airflow/auth
|
||||
|
||||
x-generator-common: &generator-common
|
||||
image: clickstream-generator:local
|
||||
build:
|
||||
context: .
|
||||
dockerfile: generator/Dockerfile
|
||||
restart: "no"
|
||||
depends_on:
|
||||
kafka-init:
|
||||
condition: service_completed_successfully
|
||||
# Читать топик движок Kafka начинает не при своём создании, а когда над ним
|
||||
# появляется матвью приёма, и она создаётся последней по номеру файла
|
||||
# (sql/ddl/40-stg-views.sql). Отправь генератор события раньше — они лягут в
|
||||
# топик и молча минуют хранилище.
|
||||
clickhouse-init:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
# Адрес брокера и имя топика — факты стенда, и называет их стенд.
|
||||
# Остальное (день, зерно, число дней, предел пачки) приходит аргументами
|
||||
# от того, кто запускает: у службы нет позиции на оси мира.
|
||||
KAFKA_BOOTSTRAP_SERVERS: ${KAFKA_BOOTSTRAP_SERVERS:-kafka:9092}
|
||||
KAFKA_TOPIC: ${KAFKA_TOPIC:-hits}
|
||||
|
||||
x-superset-common: &superset-common
|
||||
image: clickstream-superset:local
|
||||
build:
|
||||
@@ -194,25 +216,6 @@ services:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
generator:
|
||||
profiles: ["generator"]
|
||||
build:
|
||||
context: .
|
||||
dockerfile: generator/Dockerfile
|
||||
restart: "no"
|
||||
depends_on:
|
||||
kafka-init:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
# Адрес брокера и имя топика — факты стенда, и называет их стенд.
|
||||
# Остальное (день, зерно, число дней, предел пачки) приходит аргументами
|
||||
# от того, кто запускает: у службы нет позиции на оси мира.
|
||||
KAFKA_BOOTSTRAP_SERVERS: ${KAFKA_BOOTSTRAP_SERVERS:-kafka:9092}
|
||||
KAFKA_TOPIC: ${KAFKA_TOPIC:-hits}
|
||||
command: ["batch"]
|
||||
# До #42 от этой разовой службы нет зависимого: включать её в обычный
|
||||
# `up --wait` нельзя, иначе успешное завершение будет считаться сбоем.
|
||||
|
||||
# DDL применяется с ноды 1 по порядку имён файлов после готовности всего кластера.
|
||||
clickhouse-init:
|
||||
image: ${CLICKHOUSE_IMAGE:-clickhouse/clickhouse-server:26.3.17.56}
|
||||
@@ -244,6 +247,27 @@ services:
|
||||
volumes:
|
||||
- ./sql/ddl:/ddl:ro
|
||||
|
||||
# Стартовый мир: восемь модельных дней уезжают в топик при каждом подъёме.
|
||||
# Что это за дни и каким мир обязан выйти — data/world-inventory.json.
|
||||
#
|
||||
# Число дней стоит здесь числом: YAML не читает Python, и одно из двух мест
|
||||
# (второе — `STARTING_DAYS` в inventory.py) лишнее по построению. Разъедутся
|
||||
# они — покраснеют счётчики `make check-clickhouse`.
|
||||
#
|
||||
# Повторный `make up` заливает мир заново, и это не оплошность: `WatchID` у
|
||||
# событий те же, ReplacingMergeTree схлопнет повтор в ODS. Сырьё в STG при
|
||||
# этом честно удвоится — свойство слоя, описанное в storage.md.
|
||||
world-init:
|
||||
<<: *generator-common
|
||||
command: ["batch", "--day", "0", "--days", "8"]
|
||||
|
||||
# Тот же образ для ручных прогонов: `make generate-batch`, `make generate-live`.
|
||||
# Под профилем — чтобы обычный подъём стенда её не трогал.
|
||||
generator:
|
||||
<<: *generator-common
|
||||
profiles: ["generator"]
|
||||
command: ["batch"]
|
||||
|
||||
postgres-metadata:
|
||||
image: ${POSTGRES_IMAGE:-postgres:16-alpine}
|
||||
restart: unless-stopped
|
||||
@@ -285,6 +309,13 @@ services:
|
||||
# упавшим для --wait.
|
||||
clickhouse-init:
|
||||
condition: service_completed_successfully
|
||||
# По той же причине — и ещё по одной. Заливка стартового мира идёт
|
||||
# последней в цепи разовых служб, и зависимого ей взять больше негде.
|
||||
# Заодно это правда про порядок: даг `next_day` этапа 5 продолжает ось с
|
||||
# того дня, на котором заливка остановилась, — Airflow приходит в мир,
|
||||
# который уже есть.
|
||||
world-init:
|
||||
condition: service_completed_successfully
|
||||
entrypoint: ["/bin/bash"]
|
||||
command: ["/opt/airflow/init.sh"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user