docs(world): описан жизненный цикл прикладного мира
- Зачем: - границы владения Compose и Airflow должны быть видны менти из одного источника истины. - Что: - добавлены спека и ADR жизненного цикла мира; - обновлены README, архитектурные справочники и прежние решения; - правило полной очистки записано как явное и проверяемое требование к агенту. - Проверка: - документация вычитана через `ai-text-lint` и `writing-for-agents`; - выполнена литературная вычитка русского текста; - `git diff --check`.
This commit is contained in:
1 parent
fc5244cc67
commit
7e6554507a
12 files changed
+499
-104
No files matched your search
@@ -480,44 +480,35 @@ Airflow читает и собирает эти файлы штатным шаб
|
||||
|
||||
Порядок остальных задают два правила. Первое: матвью принадлежит слою своей
|
||||
цели, а не источника, — разбор из STG в ODS лежит среди файлов ODS, потому что
|
||||
наполняет ODS. Второе: матвью приёма создаётся последней из всех, и потому нарушает
|
||||
нумерацию слоёв. Kafka-движок начинает читать топик ровно тогда, когда к нему
|
||||
наполняет ODS. Второе: матвью приёма создаётся последней из всех, и потому
|
||||
нарушает нумерацию слоёв. Kafka-движок начинает читать топик, когда к нему
|
||||
привязывают первую матвью; создай её раньше разбора — и всё, что доедет в
|
||||
зазоре, ляжет в сырьё и не попадёт в ODS никуда, ни в событие, ни в ошибки. На
|
||||
пустом топике зазор безвреден, поэтому первый прогон о нём не скажет. Проснётся
|
||||
он, когда тома ClickHouse снесены, а данные Kafka целы, — то есть на обычной
|
||||
отладке.
|
||||
|
||||
Применение — двумя одноразовыми сервисами при `make up`, по образцу уже
|
||||
работающих `airflow-init` и `superset-init`. Сначала `kafka-init` создаёт топики
|
||||
— `hits` с двумя партициями и `orders` с одной ([ADR
|
||||
0008](../adr/0008-order-ingestion.md)), — затем `clickhouse-init` дожидается его
|
||||
завершения и применяет файлы с ноды 1: всё `ON CLUSTER`, кроме чтеца заказов —
|
||||
он объявлен только на этой ноде. Порядок страхует `hits` от автосоздания с
|
||||
одной партицией. Переключателей тут два, и путать их не надо: брокер
|
||||
автосоздание разрешает, а потребитель librdkafka внутри ClickHouse его не
|
||||
просит — оба конца измерены, см. «Что проверено». То есть стенд держится на
|
||||
умолчании клиента, а урок «обе ноды читают топик» умирает тихо, поэтому топик и
|
||||
создаётся явно, до применения DDL.
|
||||
Файлы применяет даг `world_initialize` с ноды 1 отдельной учётной записью
|
||||
`lifecycle`: всё `ON CLUSTER`, кроме чтеца заказов — он объявлен только на этой
|
||||
ноде. Перед DDL даг создаёт `hits` с двумя партициями и `orders` с одной
|
||||
([ADR 0008](../adr/0008-order-ingestion.md)). Этот порядок не даёт `hits`
|
||||
автоматически создаться с одной партицией. Брокер автосоздание разрешает, а
|
||||
потребитель librdkafka внутри ClickHouse его не просит. Оба конца измерены;
|
||||
результаты приведены в разделе «Что проверено». Успех дага означает больше,
|
||||
чем применённый DDL: оба стартовых
|
||||
источника приняты, а позиция мира установлена последней задачей. Полный граф и
|
||||
состояния отказа описаны в [спеке жизненного цикла](../specs/2026-08-21-world-lifecycle.md).
|
||||
|
||||
Образцы копируются не целиком, и в двух местах. `clickhouse-init` обязан ждать
|
||||
готовности **обеих** нод: `ON CLUSTER` ждёт исполнения на всех хостах и по
|
||||
таймауту бросает, а `airflow-init` ждёт только первую ноду, `superset-init` —
|
||||
только вторую. И второе: оба образца переживают `make up --wait` лишь потому, что
|
||||
от них зависят долгоживущие сервисы. Что делает `--wait` с одноразовым сервисом
|
||||
без зависимых, проверено при исполнении #37 на Docker Compose 2.40.3: считает
|
||||
его упавшим и возвращает единицу, хотя контейнер вышел с нулём. Поэтому
|
||||
зависимые есть и у новой пары: `clickhouse-init` ждёт `kafka-init`, а
|
||||
`airflow-init` — `clickhouse-init`, и цепочка упирается в долгоживущий Airflow.
|
||||
Побочная выгода важнее обхода `--wait`: к моменту старта Airflow DDL заведомо
|
||||
применён.
|
||||
|
||||
Повторный `make up` поверх живого тома проходит зелёным: весь DDL идёт через
|
||||
`CREATE ... IF NOT EXISTS`. Оборотная сторона — изменённый объект тем же
|
||||
запуском не применяется, причём молча. Отдельного механизма для этого нет и не
|
||||
нужно: правка существующего DDL случается, только пока стенд пишут, а лекарство
|
||||
уже есть — `make clean && make up`. Мир регенерируется, сырьё живёт трое суток,
|
||||
терять нечего.
|
||||
Повторный `make up` поверх готового мира проходит зелёным без изменений:
|
||||
`world_initialize` ветвится раньше DDL. Поэтому изменённый объект обычным
|
||||
подъёмом не применяется. В разработке меняют или пересоздают только затронутый
|
||||
объект, партицию либо базу слоя. Если нужен целиком канонический мир,
|
||||
`make rebuild-storage` запускает `world_recreate`: тот удаляет прикладные базы
|
||||
`stg`, `dm`, `dds`, `ods`, `dic`, позиции групп потребителей и прикладные топики,
|
||||
затем вызывает `world_initialize`. Службы и их тома остаются на месте, а позиция
|
||||
возвращается к концу стартовых дней. Полный `make clean` для изменения DDL не
|
||||
нужен. Когда какая область очистки уместна перед проверкой, задаёт
|
||||
[карта проверок](testing.md).
|
||||
|
||||
## Карта таблиц
|
||||
|
||||
|
||||
Reference in new issue
Block a user