- Зачем: - границы владения Compose и Airflow должны быть видны менти из одного источника истины. - Что: - добавлены спека и ADR жизненного цикла мира; - обновлены README, архитектурные справочники и прежние решения; - правило полной очистки записано как явное и проверяемое требование к агенту. - Проверка: - документация вычитана через `ai-text-lint` и `writing-for-agents`; - выполнена литературная вычитка русского текста; - `git diff --check`.
5.3 KiB
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 DDL больше не принадлежит
etl: прикладную структуру ведёт отдельныйlifecycle. - В ADR 0009 отсутствие
world_positionбольше не означает готовый стартовый мир. Начальную позицию ставитworld_initialize, а работники принимают только8и больше. - Одноразовые службы Compose и shell-ожидание, описанные прежним устройством хранилища, отменены. Их последовательность стала наблюдаемым графом Airflow.
Отклонено
- Оставить создание мира в Compose, а позицию исправлять из
make rebuild-storage: работает технически, но сохраняет двух оркестраторов одного процесса. - Один безусловно разрушительный даг для первого и повторного запуска: обычный
make upмог бы стереть уже прожитые дни. - Отдельная переменная состояния мира: она дублировала бы
world_positionи могла разойтись с ней. Значения-1и0выражают нужные переходы в одном месте. - Выдать обычной учётной записи
etlправо удаления баз: рабочий конвейер не должен получать административные права из-за редкой операции восстановления.