- Зачем:
- список DAG'ов должен читаться лесенкой ddl_init → world_init →
world_next_day, а путь менти — проходиться пустыми формами
(issue #4, спека редизайна пути менти, решения 2–3).
- Что:
- generator_control переименован в world_init, дефолт операции —
import; next-day ушёл из выпадашки в отдельный DAG;
- новый беспараметрный world_next_day: расписание */30 * * * *,
создаётся на паузе, catchup=False, max_active_runs=1; общие
задачи вынесены в airflow/dags/utils/startup_history_tasks.py;
- доки и контрактные тесты обновлены синхронно; быстрый старт
README — без make ddl, схему создаёт DAG ddl_init.
- Проверка:
- make test (210 + 31) и make lint зелёные;
- живая приёмка на чистом стенде: world_init пустой формой
импортировал эталонный мир за 217 с (3 дня, 280 437 событий),
world_next_day после снятия с паузы добавляет ровно один день
за прогон, дашборд Superset собирается.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
70 lines
2.1 KiB
Python
70 lines
2.1 KiB
Python
"""DAG добавления одного модельного дня в мир стенда."""
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
from airflow import DAG
|
|
from airflow.operators.python import PythonOperator
|
|
from airflow.operators.trigger_dagrun import TriggerDagRunOperator
|
|
|
|
from utils.startup_history_tasks import (
|
|
assert_target_dag_not_paused,
|
|
check_manifest_task,
|
|
precheck_next_day,
|
|
run_next_day_task,
|
|
)
|
|
|
|
|
|
ETL_DAG_ID = "etl_pipeline"
|
|
|
|
default_args = {
|
|
"owner": "airflow",
|
|
"depends_on_past": False,
|
|
"email_on_failure": False,
|
|
"email_on_retry": False,
|
|
"retries": 0,
|
|
"retry_delay": timedelta(minutes=1),
|
|
}
|
|
|
|
|
|
# Context7, Airflow 2.10.5: schedule принимает cron-строку. Расписание задано
|
|
# заранее, но новый DAG остаётся на паузе до отдельного решения.
|
|
with DAG(
|
|
dag_id="world_next_day",
|
|
description="Добавление одного модельного дня в мир стенда",
|
|
default_args=default_args,
|
|
schedule="*/30 * * * *",
|
|
start_date=datetime(2024, 1, 1),
|
|
catchup=False,
|
|
max_active_runs=1,
|
|
is_paused_upon_creation=True,
|
|
tags=["generator", "startup-history"],
|
|
) as dag:
|
|
check_etl_not_paused = PythonOperator(
|
|
task_id="check_etl_not_paused",
|
|
python_callable=assert_target_dag_not_paused,
|
|
op_kwargs={"dag_id": ETL_DAG_ID},
|
|
)
|
|
precheck = PythonOperator(
|
|
task_id="precheck_next_day",
|
|
python_callable=precheck_next_day,
|
|
)
|
|
generate = PythonOperator(
|
|
task_id="run_next_day",
|
|
python_callable=run_next_day_task,
|
|
)
|
|
trigger_etl = TriggerDagRunOperator(
|
|
task_id="trigger_etl",
|
|
trigger_dag_id=ETL_DAG_ID,
|
|
conf={"full_refresh": True},
|
|
wait_for_completion=True,
|
|
allowed_states=["success"],
|
|
failed_states=["failed"],
|
|
poke_interval=30,
|
|
)
|
|
check = PythonOperator(
|
|
task_id="check_after_etl",
|
|
python_callable=check_manifest_task,
|
|
)
|
|
|
|
check_etl_not_paused >> precheck >> generate >> trigger_etl >> check
|