我试图使用ExternalTaskSensor,但却陷入了另一个DAG的任务中,该任务已经成功完成。
这里,第一个DAG" a"完成任务,然后完成第二个DAG" b"通过ExternalTaskSensor应该被触发。相反,它陷入了寻找a.first_task的困境。
第一个DAG:
import datetime
from airflow import DAG
from airflow.operators.python_operator import PythonOperator
dag = DAG(
dag_id='a',
default_args={'owner': 'airflow', 'start_date': datetime.datetime.now()},
schedule_interval=None
)
def do_first_task():
print('First task is done')
PythonOperator(
task_id='first_task',
python_callable=do_first_task,
dag=dag)
第二个DAG:
import datetime
from airflow import DAG
from airflow.operators.python_operator import PythonOperator
from airflow.operators.sensors import ExternalTaskSensor
dag = DAG(
dag_id='b',
default_args={'owner': 'airflow', 'start_date': datetime.datetime.now()},
schedule_interval=None
)
def do_second_task():
print('Second task is done')
ExternalTaskSensor(
task_id='wait_for_the_first_task_to_be_completed',
external_dag_id='a',
external_task_id='first_task',
dag=dag) >> \
PythonOperator(
task_id='second_task',
python_callable=do_second_task,
dag=dag)
我在这里缺少什么?
答案 0 :(得分:10)
ExternalTaskSensor
假设您依赖于具有相同执行日期的dag运行中的任务。
这意味着,在您的情况下,dags a
和b
需要按照相同的时间表运行(例如,每天上午9:00或w / e)。
否则,在实例化execution_delta
时,您需要使用execution_date_fn
或ExternalTaskSensor
。
以下是运营商内部的文档,以帮助进一步澄清:
:param execution_delta: time difference with the previous execution to
look at, the default is the same execution_date as the current task.
For yesterday, use [positive!] datetime.timedelta(days=1). Either
execution_delta or execution_date_fn can be passed to
ExternalTaskSensor, but not both.
:type execution_delta: datetime.timedelta
:param execution_date_fn: function that receives the current execution date
and returns the desired execution date to query. Either execution_delta
or execution_date_fn can be passed to ExternalTaskSensor, but not both.
:type execution_date_fn: callable
答案 1 :(得分:7)
为弄清我在这里和其他相关问题上看到的内容,达格犬不一定必须按照接受的答案中所述的相同时间表运行。冒充者也不必具有相同的start_date
。如果您创建的ExternalTaskSensor
任务没有execution_delta
或execution_date_fn
,则两个dag必须具有相同的执行日期。碰巧的是,如果两个dag具有相同的计划,则每个时间间隔中的计划运行将具有相同的执行日期。我不确定手动触发计划的dag的执行日期。
为使此示例正常工作,dag b
的{{1}}任务需要一个ExternalTaskSensor
或execution_delta
参数。如果使用execution_date_fn
参数,则应确保execution_delta
的执行日期-b
= execution_delta
的执行日期。如果使用a
,则该函数应返回execution_date_fn
的执行日期。
如果您使用的是a
,然后使用TriggerDagRunOperator
来检测该dag何时完成,则可以执行以下操作:将主dag的执行日期传递给{{1 }}的ExternalTaskSensor
参数,例如TriggerDagRunOperator
。这样,两个dag的执行日期将是相同的,并且您将不需要每个dag的时间表都相同,也不需要使用execution_date
或execution_date='{{ execution_date }}'
传感器参数。
以上内容是在Airflow 1.10.9上编写和测试的
答案 2 :(得分:0)
从Airflow v1.10.7开始,tomcm的答案不正确(至少对于此版本而言)。如果外部DAG的时间表不同,则应使用execution_delta
或execution_date_fn
确定外部DAG的日期和时间表。
答案 3 :(得分:0)
从我成功的案例来看:
default_args = {
'owner': 'xx',
'retries': 2,
'email': ALERT_EMAIL_ADDRESSES,
'email_on_failure': True,
'email_on_retry': False,
'retry_delay': timedelta(seconds=30),
# avoid stopping tasks after one day
'depends_on_past': False,
}
dag = DAG(
dag_id = dag_id,
# get the datetime type value
start_date = pendulum.strptime(current_date, "%Y, %m, %d, %H").astimezone('Europe/London').subtract(hours=1),
description = 'xxx',
default_args = default_args,
schedule_interval = timedelta(hours=1),
)
...
external_sensor= ExternalTaskSensor(
task_id='ext_sensor_task_update_model',
external_dag_id='xxx',
external_task_id='xxx'.format(log_type),
# set the task_id to None because of the end_task
# external_task_id = None,
dag=dag,
timeout = 300,
)
...
您可以等到成功自动触发任务为止。请勿手动执行,开始日期会有所不同。