Отдать жизненный цикл мира дагам Airflow #119
Notifications
Due Date
No due date set.
Blocks
#124 Перевести Airflow на официальный провайдер ClickHouse
ddmitry/clickstream-data-platform
Reference: ddmitry/clickstream-data-platform#119
Reference in new issue
Block a user
Источник истины — спека
«Жизненный цикл мира: создание и пересоздание ведёт Airflow»
и ADR 0013.
Задача одна и делится только на коммиты: несколько связных коммитов внутри неё
— нормально, дробить её на дочерние тикеты не надо.
Цель
Прикладная схема, данные стартового мира и позиция модельного времени
переезжают к Airflow. Compose остаётся с долгоживущими службами и
инфраструктурой,
make— с подъёмом стенда и вызовом нужного дага. Менти видитодин наблюдаемый граф вместо процесса, размазанного между Compose, shell и
Airflow.
Сначала прочитать
docs/specs/2026-08-21-world-lifecycle.md— контракты дагов, состоянияпозиции, поведение при отказах, границы;
docs/adr/0013-world-lifecycle.md— решение и доводы;docs/adr/0007-clickhouse-access.md— модель доступа, куда добавляется новаяучётная запись;
docs/adr/0008-order-ingestion.mdиdocs/adr/0009-world-control.md—устройство приёма заказов и пульта мира;
docs/architecture/storage.md, раздел «Раскладка SQL» — как сегодняприменяется DDL и почему матвью приёма создаётся последней;
docs/architecture/testing.md— карта целей и правило оmake clean;compose.yaml,Makefile,dags/world_control.py,dags/orders_ingest.py,infra/airflow/init.sh,infra/clickhouse/users.d/access.xml,scripts/wait-for-world.sh,scripts/ingest-starting-orders.sh.Критерии приёмки
Compose и
makekafka-init,clickhouse-init,world-initиworld-snapshotsвcompose.yamlнет — ни под профилем, ни как целиcompose run.исчезнувших одноразовых служб,
docker compose up --waitвозвращаетноль.
make upподнимает инфраструктуру, зовётworld_initializeчерез REST APIAirflow и ждёт результата.
make rebuild-storageзовётworld_recreateи ждёт результата.scripts/run-dag.sh) запускаетназванный даг и ждёт конца; печатает идентификатор дага, идентификатор
прогона, итоговое состояние и — при отказе — что делать дальше. Потолок
ожидания назван пределом, а не бюджетом, и взят с кратным запасом от
замера.
scripts/wait-for-world.shиscripts/ingest-starting-orders.shудалены:их работа переехала в даг и в помощника.
make generate-batchиmake generate-liveработают; унаследованныезависимости от исчезнувших служб сняты.
make cleanне тронут.Доступ
access.xmlпоявилась учётная записьlifecycleс рольюlifecycle_owner: администрирование прикладных базstg,ods,dds,dm,dicи кластерный DDL; чтениеsystem.settings; административныхправ на системные базы нет.
etlне расширены..env, образец добавлен в.env.example, подключениезаводит
infra/airflow/init.sh.world_initializemax_active_runs = 1.0—создаёт мир;
-1— краснеет и зовёт повторитьmake rebuild-storage;значения от
1доWORLD_STARTING_DAYS - 1— краснеют как недопустимые;WORLD_STARTING_DAYSи больше — пишет в журнал, что мир уже есть, изеленеет, не трогая DDL, данные и позицию.
hits— две партиции,orders— одна;повторный запуск подтверждает эти числа или падает с понятной ошибкой.
sql/ddl/по порядку имён файлов, с ноды1, учётной записью
lifecycle.ods.event_distза даты описи иods.event_errors_distне меньше суммысобытий из
data/world-inventory.json. Опись смонтирована в Airflow толькодля чтения.
orders_ingestдёргаетсяждущим триггером.
WORLD_STARTING_DAYSпоследней успешной задачей.world_recreate-1до первого удаления; прикладные базыудаляются первыми; затем удаляются позиции групп
clickstream_hits,clickstream_orders, после них — топикиhits,orders; позиция0только после успешной очистки; дальше ждущий триггер
world_initialize.world_initializeнет — переиспользованиеидёт делегированием.
Работники мира
world_next_dayиworld_live_dayкраснеют, когда позиции нет либо онаменьше
WORLD_STARTING_DAYS; отказ называет прочитанное значение иследующий шаг.
orders_ingestсторожа не получил.Документация тем же PR
AGENTS.md,README.md, обе спеки(
2026-07-30-stand-v2-realism.md,2026-08-01-generator.md),docs/adr/0009-world-control.md,docs/architecture/storage.md,docs/architecture/testing.md,docs/architecture/orders/start-world.md, комментарииcompose.yaml,комментарий про
world-initвgenerator/src/clickstream_generator/inventory.pyи комментарий про
kafka-initвsql/ddl/10-stg-tables.sql.значит «стартовый мир уже есть» (спека генератора, раздел 8; ADR 0009;
README); Compose больше не владеет созданием мира (storage.md, «Раскладка
SQL»); DDL применяет не
etl, аlifecycle(ADR 0007).make upи пересборки записаны вdocs/architecture/testing.md, «Что проверено», и названы в теле PR.Границы
world_liveв этойзадаче нет — предусловие обслуживания живёт словами в спеке и README.
makeне добавляем: вопрос «данные правильные» — к дагам DQ(
docs/architecture/testing.md).make cleanв реализацию и обычную проверку не входит.Подводные камни
clickhouse-client --multiqueryисполняет файл целиком. Новый путь обязан сохранить это свойство; API клиента
и допустимый способ разбора сначала сверить через MCP Context7, решение
коротко записать в коде или документации.
generator/,data/и корневой.dockerignore. Локальные.venvи кеши в контекст ехатьне должны. Задачу сборки замерить отдельно и назвать её цену в теле PR.
недопустимо. Отсюда порядок «сначала базы, затем группы и топики»; на живом
стенде проверить, что после удаления баз группы освободились.
WORLD_STARTING_DAYSостаётся в двух местах — вcompose.yamlи вinventory.pyгенератора. После переезда у числа в YAML один потребитель;комментарий в генераторе должен указывать на него, а не на исчезнувшую службу.
TriggerDagRunOperator,DockerOperatorи сборка образа) и DDL ClickHouse — сверять через MCP Context7 и коротко
фиксировать, что проверили.
Проверка
Команды:
Сценарии на живом стенде:
make upна готовом мире — быстро, зелёно, позиция неизменилась, счётчики
check-clickhouseте же, в журнале дага сказано, что мируже есть.
make rebuild-storage— позиция проходит-1→0→WORLD_STARTING_DAYS; в ODS ровно даты описи; топики созданы заново, офсетыгрупп идут с нуля; службы и их тома не пересоздавались.
отрицательной позиции;
world_initializeпри позиции-1; оборваннаяочистка оставляет
-1, и следующийmake upоб этом говорит, а незаглаживает.
lifecycleбез ошибок прав, административный запрос к системной базе ей отклоняют.
make generate-batchподнимает генератор без исчезнувших зависимостей.make clean && make up— на итоговой приёмке и толькопотому, что эта работа меняет самый первый подъём стенда. Правилом это не
становится: обычная проверка обходится узкой областью очистки.