Перевести Airflow на официальный провайдер ClickHouse #124
Notifications
Due Date
No due date set.
Depends on
#119 Отдать жизненный цикл мира дагам Airflow
ddmitry/clickstream-data-platform
Reference: ddmitry/clickstream-data-platform#124
Reference in new issue
Block a user
Следует за #119. Жизненный цикл мира уже принят целиком; эта задача меняет
одну границу — способ, которым даги исполняют SQL ClickHouse.
Цель
Перевести все исполняемые SQL-файлы ClickHouse, которыми пользуются даги, на
официальный провайдер Airflow
apache-airflow-providers-clickhousedb. Файлынапрямую получает штатный
SQLExecuteQueryOperator: даг задаёт граф, порядок ипараметры, а преобразование остаётся в самодостаточном SQL своего слоя.
Программная логика с ветвлением, ожиданием или разбором результата использует
официальный
ClickHouseHook.Менти должен видеть один штатный путь SQL-интеграции Airflow, а не разбираться
в проектном разборщике, ручном открытии клиента или скрытой сборке одного
запроса из нескольких файлов.
Официальный провайдер уже совместим со стендом: Airflow 3.3.0,
apache-airflow-providers-common-sql2.0.1 иclickhouse-connect1.6.0удовлетворяют его требованиям. На момент постановки официальный реестр
содержит версии 1.0.0 и 1.0.1.
Сначала прочитать
docs/specs/2026-08-21-world-lifecycle.md;docs/adr/0013-world-lifecycle.md;docs/adr/0001-stand-services.mdиdocs/adr/0007-clickhouse-access.md;docs/architecture/storage.md, раздел «Раскладка SQL»;docs/architecture/orders/ingestion.md;dags/world_lifecycle.py,dags/orders_ingest.pyиdags/test_clickhouse.py;sql/ddl/*.sql,sql/stg/orders_raw_load.sql,sql/ods/order_load.sql,sql/ods/order_errors_load.sqlиsql/ods/_order_wire_contract.sql;infra/airflow/Dockerfileиinfra/airflow/init.sh;apache-airflow-providers-clickhousedb,ClickHouseHookиSQLExecuteQueryOperator.Критерии приёмки
apache-airflow-providers-clickhousedb. Драйверclickhouse-connect==1.6.0остаётся прямым пином: провайдер задаёт тольконижнюю границу версии, а сборка стенда должна быть воспроизводимой.
pip checkпроходит, а итоговые версии Airflow, провайдера,common-sqlиclickhouse-connectназваны в отчёте проверки.clickhouse_defaultиclickhouse_lifecycleсоздаются стипом
clickhouse, который регистрирует провайдер.SQLExecuteQueryOperator; Python-задачи не получают отрендеренный SQLаргументом и не исполняют его вручную.
sql/ddl/*.sqlисполняются сsplit_statements=Trueв порядке имён файлов. Порядок виден в графеworld_initialize: каждый файл представлен отдельной последовательносвязанной задачей.
orders_ingestисполняетsql/stg/orders_raw_load.sqlштатнымоператором и передаёт
run_idкак параметр ClickHouseload_id.sql/ods/order_parse.sql: сначала он пишет годные строки, затем брак. Общийпредикат объявлен локальной Jinja-макрокомандой в этом же файле и
разворачивается в оба выражения; отдельного
_order_wire_contract.sqlбольше нет.
parse_batch, исполняет оба выраженияпоследовательно с
split_statements=Trueи передаёт им одинload_id._ddl_statementsудалена. Вdags/нет прямыхимпортов
clickhouse_connectи вызововclickhouse_connect.get_client().специальная возможность ClickHouse, идут через официальный
ClickHouseHook.world_initializeпо-прежнему применяет весь канонический DDL от имениlifecycle; частичный отказ не переводит позицию мира в готовое состояние.world_recreateпо-прежнему удаляет только прикладные базы и сохраняетконтракт позиций
-1→0→WORLD_STARTING_DAYS.самодостаточен и подключается оператором, а Python остаётся оркестрацией.
Обновлены как минимум
docs/specs/2026-08-21-world-lifecycle.md, ADR 0001,docs/architecture/storage.md,docs/architecture/orders/ingestion.mdикомментарии образа Airflow; остальные упоминания найдены поиском и сверены.
Границы
pull_batch→parse_batch,классификацию годных строк и брака и контракт
_load_idне менять.makeне менять.
общего предиката не заводить.
make upпо-прежнему неприменяет изменённый DDL.
make cleanне запускать: провайдер не меняет постоянное состояние служб,а проверка укладывается в
make rebuild-storage.Подводные камни
resolve-library-id→query-docs, затем с официальной документациейAirflow. Коротко записать выбранную версию и причину.
SQLExecuteQueryOperatorпринимает путь к шаблону относительно каталогапоиска DAG. Смонтированный
sql/должен быть доступен всем компонентам,которые разбирают и исполняют задачу.
выражения. Макрокоманда разбора заказов живёт внутри одного файла; параметр
ClickHouse
{load_id:String}передаётся черезparameters, а не подставляетсястрокой через Jinja.
split_statements=Trueисполняет выражения последовательно, без общейтранзакции: ClickHouse не поддерживает многооперационные транзакции. Это
сохраняет нынешнее поведение, но не обещает откат уже выполненных выражений.
При частичном отказе Airflow повторяет весь
parse_batchс тем жеload_id.parse_batch: это одна классификациянеизменного среза. Два
task_idне добавили бы транзакционности, зато сновапотребовали бы дублировать предикат, собирать запрос из нескольких файлов
либо заводить постоянный классификатор.
провайдеры; итог разрешения зависимостей проверяется в собранном образе.
Проверка
На живом стенде дополнительно проверить:
world_initializeвидны последовательные задачи для всех файловsql/ddl/.orders_ingestостались два шагаpull_batch→parse_batch, аотрендерированный SQL второго шага содержит обе ветви и не содержит
неразвёрнутых Jinja-конструкций.
lifecycle, а запросыorders_ingest— пользователем подключенияclickhouse_default.make upне применяет DDL и не меняет данные.объекты из начала и конца хотя бы одного DDL-файла, а управляемая порция
заказов раскладывается и в годную ветвь, и в брак.