BranchPythonOperator之后的气流任务不会失败,并且可以正确成功

时间:2018-08-03 03:07:39

标签: python airflow

在我的DAG中,我有一些任务只能在星期六执行。因此,我使用BranchPythonOperator在星期六的任务和DummyTask之间进行分支。之后,我加入了两个分支,并希望执行其他任务。

工作流程如下: Gravity Forms
在这里,我将dummy3的触发规则设置为'one_success',一切正常。

我遇到的问题是BranchPythonOperator上游的某些操作失败时: enter image description here
BranchPythonOperator和分支正确地具有状态'upstream_failed',但是加入分支的任务变为'skipped',因此整个工作流程显示为'success'

我尝试使用'all_success'作为触发规则,但是如果某些失败使整个工作流程失败,但如果没有失败,则可以跳过dummy3。

我也尝试使用'all_done'作为触发规则,然后即使没有失败,它也可以正常工作,但是如果失败,仍然可以执行dummy3。

我的测试代码如下:

from datetime import datetime, date
from airflow import DAG
from airflow.operators.python_operator import BranchPythonOperator, PythonOperator
from airflow.operators.dummy_operator import DummyOperator

dag = DAG('test_branches',
          description='Test branches',
          catchup=False,
          schedule_interval='0 0 * * *',
          start_date=datetime(2018, 8, 1))


def python1():
    raise Exception('Test failure')
    # print 'Test success'


dummy1 = PythonOperator(
    task_id='python1',
    python_callable=python1,
    dag=dag
)


dummy2 = DummyOperator(
    task_id='dummy2',
    dag=dag
)


dummy3 = DummyOperator(
    task_id='dummy3',
    dag=dag,
    trigger_rule='one_success'
)


def is_saturday():
    if date.today().weekday() == 6:
        return 'dummy2'
    else:
        return 'today_is_not_saturday'


branch_on_saturday = BranchPythonOperator(
    task_id='branch_on_saturday',
    python_callable=is_saturday,
    dag=dag)


not_saturday = DummyOperator(
    task_id='today_is_not_saturday',
    dag=dag
)

dummy1 >> branch_on_saturday >> dummy2 >> dummy3
branch_on_saturday >> not_saturday >> dummy3

编辑

我只是想出一个丑陋的解决方法: enter image description here
dummy4代表我实际需要运行的任务,dummy5只是一个假人。
dummy3仍然具有触发规则'one_success'

现在,如果没有上游故障,则哑元3和哑元4将运行,如果星期二不是星期六,哑元5将“运行”,如果星期六是星期六,则将被跳过,这意味着DAG在这两种情况下都标记为成功。
如果上游发生故障,则将dummy3和dummy4跳过,并将dummy5标记为'upstream_failed',并将DAG标记为失败。

此变通办法可以使我的DAG正常运行,但是我仍然希望没有任何变通办法的解决方案。

2 个答案:

答案 0 :(得分:4)

您可以使用的一种解决方法是,将DAG的第二部分放在SubDAG中,就像我在说明您的示例的以下代码中所做的那样:https://gist.github.com/cosenal/cbd38b13450b652291e655138baa1aba

它可以按预期工作,并且可以说比您的解决方法更干净,因为您没有任何其他辅助虚拟运算符。但是,您失去了扁平结构,现在必须放大SubDag才能查看内部结构的详细信息。


更一般的观察:在对您的DAG进行试验之后,我得出的结论是Airflow需要类似JoinOperator之类的东西来替换您的Dummy3运算符。让我解释。您描述的行为来自以下事实:DAG的成功仅取决于最后一个运算符是否成功(或被跳过!)。

以下以“成功”状态结尾的DAG是支持上述声明的MWE。

def python1():
    raise Exception('Test failure')

dummy1 = PythonOperator(
    task_id='python1',
    python_callable=python1,
    dag=dag
)

dummy2 = DummyOperator(
    task_id='dummy2',
    dag=dag,
    trigger_rule='one_success'
)

dummy1 >> dummy2

有一个JoinOperator仅在其中一个立即父母成功并且其他所有父母都被跳过时才触发,这很酷,而不必使用trigger_rule参数。

>

或者,可以解决触发问题的all (success | skipped)可以解决您遇到的问题,您可以将其应用于Dummy3。不幸的是,我认为您还不能在气流上创建自定义触发规则。

编辑:在该答案的第一版中,我声称触发规则one_successall_success根据 all 的成功程度触发DAG中运营商的祖先,而不仅仅是直系父母。这与documentation不符,实际上,以下实验对其无效:https://gist.github.com/cosenal/b607825539aa0d308f10f3095e084fac

答案 1 :(得分:2)

在任何情况下,将dummy3的触发规则设置为'none_failed'都会使其以预期状态结束。

请参见https://airflow.apache.org/concepts.html#trigger-rules


EDIT :当问及回答此问题时,似乎'none_failed'触发规则尚不存在:它是在2018年11月添加的

请参阅https://github.com/apache/airflow/pull/4182