# ADR 0003. Уборка в DAG и состояние запуска Дата: 31 июля 2026 года. Статус: принято. ## Решение Задача уборки в DAG стенда идёт обычным правилом запуска: только после успеха всех предыдущих шагов. `trigger_rule="all_done"` и задачи-teardown в хвосте DAG не используются. Упавший DAG оставляет кластер таким, каким сломался; чистое состояние обеспечивает первая задача следующего запуска — она сносит остатки через `DROP ... IF EXISTS` и убеждается, что их нет. Правило шире уборки: в конце DAG не должно стоять задачи, которая зеленеет при отказе предыдущих. ## Почему Состояние запуска Airflow считает по концам графа: зелёные концы — зелёный запуск, а упавшее выше для итога немо. Уборка с `all_done` написана так, чтобы отработать при любом исходе, и, встав в конец, красит запуск в зелёный именно тогда, когда проверка упала. Для стенда это худший исход: `make smoke` спрашивает у Airflow одно поле — состояние запуска, — и на сломанном кластере докладывает, что пробник прошёл. Обычное правило запуска переворачивает счёт по концам в нашу пользу. После отказа выше уборка уходит в `upstream_failed`, это состояние отказа, и запуск краснеет по ней. Видны обе половины: и отказ рабочей задачи, и отказ самой уборки, если кластер жив, а снести таблицы не вышло. Документированный приём Airflow для тех, кому `all_done` в хвосте всё же нужен, — отдельная задача-сторож с правилом `one_failed`; здесь она не понадобилась. Цена решения — между падением и следующим запуском в `default` лежат служебные таблицы пробника. Размен принят: тот же выбор уже сделан для постоянного топика Kafka, который пробник не удаляет. ## Что проверено 31 июля 2026 года на живом стенде с Airflow 3.3.0. Три прогона `test_clickhouse` через API: зелёный (четыре задачи `success`, таблиц после прогона нет), красный с удалённой на ноде 2 локальной таблицей (`prepare_tables` — `failed`, остальные — `upstream_failed`, состояние запуска `failed`, следы поломки на кластере), затем снова зелёный (остатки снесены первой задачей, таблиц 0). Оба отвергнутых варианта проверены так же и оба дали `success` при упавшей проверке: уборка с `trigger_rule="all_done"` и уборка `as_teardown(on_failure_fail_dagrun=True)`. Семантика правил запуска и задач-teardown сверена через MCP Context7 по документации Airflow: раздел про setup/teardown (умолчание `on_failure_fail_dagrun=False`, правило `ALL_DONE_SETUP_SUCCESS`) и раздел лучших практик про задачу-сторож. Оттуда же взята формулировка ловушки. Правило прочитано в исходниках установленного Airflow — `airflow/models/dagrun.py`, `is_effective_leaf`: концом графа считается задача, ниже которой только задачи-teardown с `on_failure_fail_dagrun=False`, и которая сама не такова.