- Зачем: - границы владения Compose и Airflow должны быть видны менти из одного источника истины. - Что: - добавлены спека и ADR жизненного цикла мира; - обновлены README, архитектурные справочники и прежние решения; - правило полной очистки записано как явное и проверяемое требование к агенту. - Проверка: - документация вычитана через `ai-text-lint` и `writing-for-agents`; - выполнена литературная вычитка русского текста; - `git diff --check`.
68 lines
5.3 KiB
Markdown
68 lines
5.3 KiB
Markdown
# 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` право удаления баз: рабочий конвейер не
|
||
должен получать административные права из-за редкой операции восстановления.
|