👷‍♂️

DAGにTaskを追加した後、UpstreamのTaskをClearする時注意が必要だよ

2022/11/01に公開

(Airflow 2.1で確認)

今回問題にしている状況

タイトルだけだと状況がわかりにくいですが、既存のDAGに関して

  1. 間接的な依存関係にあるTask(UpstreamとDownstreamの関係)を新たに追加
  2. 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の方も実行されています。

なんで起きるか

すごく直観に反しますが、バグというより仕様だと思います。

  1. Taskを実行(clear)すると、DAG Run全体がActiveになります
  2. SchedulerはActiveな各DAG Runに対しSchedulableなTask Instanceをリストアップします
  3. リストアップした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しておく

  1. TaskをDAGのコードに追加
  2. 追加したDownstreamのTaskを「Mark success」(追加した手順)
  3. 追加したUpstreamのTaskを実行(Clear)

するとDownstreamのTaskを実行せず、UpstreamのTaskを実行(clear)できます。

(Downstreamを先にMark Suceessし、UpstreamをClearした場合のDownstreamのログ。実行されていません)

追加したDownstreamが、追加したUpstreamに直接依存するようにする

  1. TaskをDAGのコードに追加
  2. この時、追加したDownstream(t4)のTaskがUpstream(t3)に直接依存するようにする(追加した手順)
  3. 追加したUpstream(t3)のTaskを実行(Ccear)

とすると、Downstream(t4)の実行は、追加したUpstream(t3)が終わるまで始まりません(実行自体はされます)。

Discussion