Airflow 仅运行最新的气流DAG
假设我想用气流运行一个非常简单的ETL DAG: 它检查DB2中的最后一次插入时间,并将较新的行从DB1加载到DB2(如果有) 有一些可以理解的要求:Airflow 仅运行最新的气流DAG,airflow,airflow-scheduler,Airflow,Airflow Scheduler,假设我想用气流运行一个非常简单的ETL DAG: 它检查DB2中的最后一次插入时间,并将较新的行从DB1加载到DB2(如果有) 有一些可以理解的要求: 计划每小时运行一次,前几次运行将持续1小时以上 第一次运行应处理一个月的数据,持续72小时 因此,第二次运行应处理最后72小时,持续7.2小时 第三个过程7.2小时,在一小时内完成 从那时起,它每小时运行一次 DAG运行时,不要启动下一个DAG,而是跳过它 如果时间已过触发事件,且DAG未启动,则不要随后启动它 还有其他DAG,DAG应独立执
- 第一次运行应处理一个月的数据,持续72小时
- 因此,第二次运行应处理最后72小时,持续7.2小时
- 第三个过程7.2小时,在一小时内完成
- 从那时起,它每小时运行一次
取决于过去
catchup
回填
LatestOnlyOperator
注:已经有一个非常类似的,但它并不累人。这一个满足我的要求。DAG每分钟运行一次,我的“主要”任务持续90秒,因此它应该跳过每秒钟的运行。 我使用了一个
shortcircuit操作符
来检查当前运行是否是当前唯一的运行(在aiffair
db的dag\u运行
表中查询),以及catchup=False
来禁用回填。
但是,我不能正确地使用应该执行类似操作的LatestOnlyOperator
DAG文件
util.py
福比
确认:此答案基于。DAG max_active_runs=1与catchup=False组合将解决此问题。DAG max_active_runs=1与catchup=False组合,并在开始处添加一个虚拟任务(启动任务的排序),wait_for_DOWNDEMENT=True。 从LatestOnlyOperator开始-如果上一次执行尚未完成,它将有助于避免重新运行任务。 或者创建“启动”任务作为LatestOnlyOperator,并确保第一处理层的所有TAK部分都连接到它。但请注意——根据文档“注意,如果给定的DAG_运行被标记为外部触发,则不会跳过下游任务。”
import os
import sys
from datetime import datetime
import airflow
from airflow import DAG
from airflow.operators.python_operator import PythonOperator, ShortCircuitOperator
import foo
import util
default_args = {
'owner': 'airflow',
'depends_on_past': True,
'start_date': datetime(2018, 2, 13), # or any date in the past
'email': ['services@mydomain.com'],
'email_on_failure': True}
dag = DAG(
'test90_dag',
default_args=default_args,
schedule_interval='* * * * *',
catchup=False)
condition_task = ShortCircuitOperator(
task_id='skip_check',
python_callable=util.is_latest_active_dagrun,
provide_context=True,
dag=dag)
py_task = PythonOperator(
task_id="test90_task",
python_callable=foo.bar,
provide_context=True,
dag=dag)
airflow.utils.helpers.chain(condition_task, py_task)
import logging
from datetime import datetime
from airflow.hooks.postgres_hook import PostgresHook
def get_num_active_dagruns(dag_id, conn_id='airflow_db'):
# for this you have to set this value in the airflow db
airflow_db = PostgresHook(postgres_conn_id=conn_id)
conn = airflow_db.get_conn()
cursor = conn.cursor()
sql = "select count(*) from public.dag_run where dag_id = '{dag_id}' and state in ('running', 'queued', 'up_for_retry')".format(dag_id=dag_id)
cursor.execute(sql)
num_active_dagruns = cursor.fetchone()[0]
return num_active_dagruns
def is_latest_active_dagrun(**kwargs):
num_active_dagruns = get_num_active_dagruns(dag_id=kwargs['dag'].dag_id)
return (num_active_dagruns == 1)
import datetime
import time
def bar(*args, **kwargs):
t = datetime.datetime.now()
execution_date = str(kwargs['execution_date'])
with open("/home/airflow/test.log", "a") as myfile:
myfile.write(execution_date + ' - ' + str(t) + '\n')
time.sleep(90)
with open("/home/airflow/test.log", "a") as myfile:
myfile.write(execution_date + ' - ' + str(t) + ' +90\n')
return 'bar: ok'