fix(airflow): исправлен запуск пульта на свежем стенде

- Зачем:
  - свежий стенд должен доходить до generator_control без скрытых ручных шагов и зависаний.
- Что:
  - quick start явно готовит DDL и откладывает Superset init до готового DM.
  - generator_control проверяет паузу etl_pipeline до мутирующих шагов.
  - make up пересобирает Airflow и поднимает базовый набор сервисов.
- Проверка:
  - make generator-test; docker compose config --quiet; make clean; make up; make ddl.
This commit is contained in:
2026-07-05 20:47:02 +03:00
parent 108053bfc2
commit 27947cee57
7 changed files with 148 additions and 7 deletions
+47 -4
View File
@@ -10,10 +10,13 @@ from __future__ import annotations
from datetime import datetime, timedelta
from airflow import DAG
from airflow.exceptions import AirflowException
from airflow.models.dag import DagModel
from airflow.models.param import Param
from airflow.operators.empty import EmptyOperator
from airflow.operators.python import BranchPythonOperator, PythonOperator
from airflow.operators.trigger_dagrun import TriggerDagRunOperator
from airflow.utils.session import provide_session
from airflow.utils.trigger_rule import TriggerRule
from airflow_clickhouse_plugin.hooks.clickhouse import ClickHouseHook
@@ -41,6 +44,8 @@ default_args = {
"retry_delay": timedelta(minutes=1),
}
ETL_DAG_ID = "etl_pipeline"
def _conf(context) -> dict:
dag_run = context.get("dag_run")
@@ -92,9 +97,9 @@ def choose_operation(**context) -> str:
"""Выбирает ветку пульта по параметру operation."""
operation = _operation(context)
if operation == "backfill":
return "precheck_backfill"
return "check_etl_not_paused_before_backfill"
if operation == "import":
return "precheck_import"
return "check_etl_not_paused_before_import"
if operation == "check":
return "check_only"
raise ValueError(f"Неизвестная операция: {operation}")
@@ -144,6 +149,27 @@ def check_manifest_task(**context) -> None:
assert_clickhouse_matches_manifest(manifest, hook)
@provide_session
def assert_target_dag_not_paused(dag_id: str, session=None) -> None:
"""
Проверяет, что зависимый DAG можно запустить.
Context7: для Airflow 2.10.5 у старого TriggerDagRunOperator нет надёжного
fail_when_dag_is_paused, поэтому паузу проверяем заранее через DagModel.
"""
dag_model = session.query(DagModel).filter(DagModel.dag_id == dag_id).one_or_none()
if dag_model is None:
raise AirflowException(
f"DAG {dag_id} ещё не найден Airflow. Подождите парсинга DAG-файлов "
"или перезапустите Airflow через make up."
)
if dag_model.is_paused:
raise AirflowException(
f"DAG {dag_id} стоит на паузе: снимите паузу в Airflow UI, "
"затем повторите generator_control."
)
with DAG(
dag_id="generator_control",
description="Пульт стартовой истории генератора",
@@ -224,9 +250,20 @@ with DAG(
python_callable=run_import_task,
)
check_etl_not_paused_before_backfill = PythonOperator(
task_id="check_etl_not_paused_before_backfill",
python_callable=assert_target_dag_not_paused,
op_kwargs={"dag_id": ETL_DAG_ID},
)
check_etl_not_paused_before_import = PythonOperator(
task_id="check_etl_not_paused_before_import",
python_callable=assert_target_dag_not_paused,
op_kwargs={"dag_id": ETL_DAG_ID},
)
trigger_etl = TriggerDagRunOperator(
task_id="trigger_etl",
trigger_dag_id="etl_pipeline",
trigger_dag_id=ETL_DAG_ID,
conf={"full_refresh": True},
wait_for_completion=True,
allowed_states=["success"],
@@ -250,7 +287,13 @@ with DAG(
trigger_rule=TriggerRule.NONE_FAILED_MIN_ONE_SUCCESS,
)
route >> [precheck_backfill_task, precheck_import_task, check_only]
route >> [
check_etl_not_paused_before_backfill,
check_etl_not_paused_before_import,
check_only,
]
check_etl_not_paused_before_backfill >> precheck_backfill_task
check_etl_not_paused_before_import >> precheck_import_task
precheck_backfill_task >> backfill_task >> trigger_etl
precheck_import_task >> import_task >> trigger_etl
trigger_etl >> check_after_etl >> done