I have a workflow where I have two parallel processes (sentinel_run and sentinel_skip) which should run or be skipped based on a condition, and then join together (resolve). I need tasks directly downstream of either sentinel_ task to have cascaded skipping, but when it gets to the resolve task, resolve should run unless there are failures in either process upstream.
Based on the documentation, the "none_failed" trigger rule should work:
none_failed: all parents have not failed (failed or upstream_failed) i.e. all parents have succeeded or been skipped
and it's also an answer to a related question.
However, when I implemented a trivial example, that's not what I'm seeing:
from airflow.models import DAG
from airflow.operators.dummy_operator import DummyOperator
from airflow.operators.python_operator import ShortCircuitOperator
from airflow.utils.dates import days_ago
dag = DAG(
"testing",
catchup=False,
schedule_interval="30 12 * * *",
default_args={
"owner": "test@gmail.com",
"start_date": days_ago(1),
"catchup": False,
"retries": 0
}
)
start = DummyOperator(task_id="start", dag=dag)
sentinel_run = ShortCircuitOperator(task_id="sentinel_run", dag=dag, python_callable=lambda: True)
sentinel_skip = ShortCircuitOperator(task_id="sentinel_skip", dag=dag, python_callable=lambda: False)
a = DummyOperator(task_id="a", dag=dag)
b = DummyOperator(task_id="b", dag=dag)
c = DummyOperator(task_id="c", dag=dag)
d = DummyOperator(task_id="d", dag=dag)
e = DummyOperator(task_id="e", dag=dag)
f = DummyOperator(task_id="f", dag=dag)
g = DummyOperator(task_id="g", dag=dag)
resolve = DummyOperator(task_id="resolve", dag=dag, trigger_rule="none_failed")
start >> sentinel_run >> a >> b >> c >> resolve
start >> sentinel_skip >> d >> e >> f >> resolve
resolve >> g
This code creates the following dag:
The issue is that the resolved task should execute (because nothing upstream is either upstream_failed or failed), but it's skipping instead.
I've introspected the database, and there aren't any failed or upstream failed tasks hiding, and I can't figure out why it wouldn't honor the "none_failed" logic.
I know about the "ugly workaround" and have implemented it in other workflows, but it adds another task to execute, and increases the complexity that new users to the DAG have to grok (especially when you multiply this by multiple tasks...). This was my primary reason for upgrading from Airflow 1.8 to Airflow 1.10, so I'm hoping there's just something obvious I'm missing...

