# ADR 0013. Жизненный цикл мира ведёт Airflow Дата: 21 августа 2026 года. Статус: принято. Реализация — тикет #119. ## Решение Compose поднимает службы стенда. Airflow владеет прикладным миром: топиками Kafka, DDL прикладных баз ClickHouse, стартовыми данными и позицией модельного времени. `make` поднимает инфраструктуру и через REST API запускает нужный даг, дожидаясь его результата. Безопасный даг `world_initialize` создаёт мир, если тот ещё не создан. На готовом мире он ничего не меняет и успешно сообщает об этом в журнале. Разрушительный даг `world_recreate` очищает прикладные базы, топики и позиции их потребителей, затем запускает `world_initialize` и ждёт его завершения. Канонический DDL применяет отдельная учётная запись Airflow с правами только на прикладную структуру стенда. `world_position` остаётся единственным состоянием пульта: - переменной нет — стенд ещё не инициализировали; - `-1` — прежний мир признан недействительным, очистка не завершена; - `0` — мир очищен и готов к начальной генерации; - `8` и больше — первый несыгранный день готового мира. `world_recreate` ставит `-1` до первого удаления и `0` только после успешной очистки. `world_initialize` принимает отсутствие позиции или `0`, а значение `8` и больше считает готовым миром. Позиция становится `8` последней задачей, после генерации стартовых дней и успешного приёма обоих источников. Обычные даги движения мира работают только с готовой позицией. ## Почему Прежняя цепочка делила один процесс между Compose, shell-скриптами и Airflow: одноразовые службы создавали стартовые данные, отдельный сценарий ждал их приёма, а пересборка сама исправляла внутреннюю переменную пульта. Из-за этой границы успешная отправка в Kafka выдавалась за создание мира, повторный `make up` смешивался с инициализацией данных, а узкая пересборка сохраняла в Kafka сообщения и офсеты прежнего мира. Airflow уже ведёт последующие дни и приём заказов. Отдав ему начало той же оси, получаем один наблюдаемый процесс и одну точку успеха: зелёный `world_initialize` означает, что схема создана, стартовый мир принят и его следующий день известен. ## Что это решение уточняет - В [ADR 0007](0007-clickhouse-access.md) DDL больше не принадлежит `etl`: прикладную структуру ведёт отдельный `lifecycle`. - В [ADR 0009](0009-world-control.md) отсутствие `world_position` больше не означает готовый стартовый мир. Начальную позицию ставит `world_initialize`, а работники принимают только `8` и больше. - Одноразовые службы Compose и shell-ожидание, описанные прежним устройством хранилища, отменены. Их последовательность стала наблюдаемым графом Airflow. ## Отклонено - Оставить создание мира в Compose, а позицию исправлять из `make rebuild-storage`: работает технически, но сохраняет двух оркестраторов одного процесса. - Один безусловно разрушительный даг для первого и повторного запуска: обычный `make up` мог бы стереть уже прожитые дни. - Отдельная переменная состояния мира: она дублировала бы `world_position` и могла разойтись с ней. Значения `-1` и `0` выражают нужные переходы в одном месте. - Выдать обычной учётной записи `etl` право удаления баз: рабочий конвейер не должен получать административные права из-за редкой операции восстановления.