👷♂️
DAGにTaskを追加した後、UpstreamのTaskをClearする時注意が必要だよ
(Airflow 2.1で確認)
今回問題にしている状況
タイトルだけだと状況がわかりにくいですが、既存のDAGに関して
- 間接的な依存関係にあるTask(UpstreamとDownstreamの関係)を新たに追加
- UpstreamのTaskだけを実行(clear)する
したとします。
AirlfowのTaskを実行(clear)する時は、本来
- そのTaskだけを実行するか
- DownstreamのTaskも実行するか
を選べるのですが、上の状況(後からTaskの追加)では、Taskだけを実行を選んでも、DowstreamのTaskも実行されます。
試してみる
例えば、t1とt2のTaskからなるDAGがあり、また、過去に動いたDAG Runがあるとします。
DAG Runの実行後、t3とt4というTaskを追加します。t3とt4は間接的な依存関係(t3>>t2>>t4)があり、どちらもstatusはNone(これまで実行されておらず、そのスケジュールも無い)の状態です。
ここで、Upstreamにあるt3だけを実行(clear)します。
(Clearの欄のDownstreamのチェックを外してclear)
確認画面に表示されるClear対象のTaskもt3だけです。
ところが、実際に実行(clear)するとt4の方も実行されています。
なんで起きるか
すごく直観に反しますが、バグというより仕様だと思います。
- Taskを実行(clear)すると、DAG Run全体がActiveになります
- SchedulerはActiveな各DAG Runに対しSchedulableなTask Instanceをリストアップします
- リストアップしたTask Instanceそれぞれに対し、依存関係(Trigger Rule)をチェックし、実行可能ならTask InstanceをScheduleする
で、今回は
- Schedule=None(今回のt4)もSchedulableとみなされる
- t4はt2にしか(直接的には)依存しない。今回はt2はすでにsuccessなので、Trigger Rule(デフォルトのall_sucess)に基づきscheduleされる
のかと思います。
これだと何がまずい(場合があるのか)のか
- UpstreamのTaskを実行(clear)すると、DownstreamのTaskが動き出します
- この時、UpstreamのTaskの終了を待たずに実行されます
- そのため、本来の依存関係とは逆の順番で処理が行われ、特に上流の方のTaskが失敗・意図しない結果になる可能性があります
- 例えば、Upstreamでクエリ実行、Downstreamでテーブルの削除をする場合、クエリ実行前にテーブルが削除される危険性があります
どうすれば良いのか
- 追加したDownstreamのTaksを事前にMark Sucessしておく
- 追加したDownstreamが、追加したUpstreamに直接依存するようにする
のどちらかで対応できそうです。
追加したDownstreamのTaksを事前にMark Sucessしておく
- TaskをDAGのコードに追加
- 追加したDownstreamのTaskを「Mark success」(追加した手順)
- 追加したUpstreamのTaskを実行(Clear)
するとDownstreamのTaskを実行せず、UpstreamのTaskを実行(clear)できます。
(Downstreamを先にMark Suceessし、UpstreamをClearした場合のDownstreamのログ。実行されていません)
追加したDownstreamが、追加したUpstreamに直接依存するようにする
- TaskをDAGのコードに追加
- この時、追加したDownstream(t4)のTaskがUpstream(t3)に直接依存するようにする(追加した手順)
- 追加したUpstream(t3)のTaskを実行(Ccear)
とすると、Downstream(t4)の実行は、追加したUpstream(t3)が終わるまで始まりません(実行自体はされます)。
Discussion