气流ExternalTask​​Sensor卡住

时间:2017-10-18 09:48:10

标签: python airflow

我试图使用ExternalTask​​Sensor,但却陷入了另一个DAG的任务中,该任务已经成功完成。

这里,第一个DAG" a"完成任务,然后完成第二个DAG" b"通过ExternalTask​​Sensor应该被触发。相反,它陷入了寻找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)

我在这里缺少什么?

4 个答案:

答案 0 :(得分:10)

ExternalTaskSensor假设您依赖于具有相同执行日期的dag运行中的任务。

这意味着,在您的情况下,dags ab需要按照相同的时间表运行(例如,每天上午9:00或w / e)。

否则,在实例化execution_delta时,您需要使用execution_date_fnExternalTaskSensor

以下是运营商内部的文档,以帮助进一步澄清:

: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_deltaexecution_date_fn,则两个dag必须具有相同的执行日期。碰巧的是,如果两个dag具有相同的计划,则每个时间间隔中的计划运行将具有相同的执行日期。我不确定手动触发计划的dag的执行日期。

为使此示例正常工作,dag b的{​​{1}}任务需要一个ExternalTaskSensorexecution_delta参数。如果使用execution_date_fn参数,则应确保execution_delta的执行日期-b = execution_delta的执行日期。如果使用a,则该函数应返回execution_date_fn的执行日期。

如果您使用的是a,然后使用TriggerDagRunOperator来检测该dag何时完成,则可以执行以下操作:将主dag的执行日期传递给{{1 }}的ExternalTaskSensor参数,例如TriggerDagRunOperator。这样,两个dag的执行日期将是相同的,并且您将不需要每个dag的时间表都相同,也不需要使用execution_dateexecution_date='{{ execution_date }}'传感器参数。

以上内容是在Airflow 1.10.9上编写和测试的

答案 2 :(得分:0)

从Airflow v1.10.7开始,tomcm的答案不正确(至少对于此版本而言)。如果外部DAG的时间表不同,则应使用execution_deltaexecution_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,
            )
...

您可以等到成功自动触发任务为止。请勿手动执行,开始日期会有所不同。