Airflow 最讓人頭痛的 start_date / execution_date

Airflow 最讓人頭痛的 start_date / execution_date

·

1 min read

Airflow 裡面的 start_dateexecution_date 對不熟悉的人說是很反直覺的。

TLDR

  • 在這篇文章中我會解釋為什麼 airflow 的 execution_date 跟我們想的不一樣

  • start_date, schedule_interval, execution_date, next_execution_date 的用法

在展開對這三個 term 的描述之前,請先記得我們在使用 airflow 的時候,如官方所建議的,都該使用 UTC+0 作為時區。

Why

start_dateexecution_date 之所以難懂,是因為一段時間的資料只有在時間過完之後才能進行處理,所以他們並不是大家字面上會以為的「任務的開始時間」、「任務的執行時間」,而是

  • 這個任務搜集的資料的開始時間

  • 這次任務搜集的資料的時間(其實也是開始時間)

什麼意思呢?

import datetime as dt
from airflow import DAG

dag = DAG(
  dag_id="some_dag",
  schedule_interval="@daily",
  start_date=dt.datetime(2023, 01, 01),
)

假設我們有一個如上面程式碼這樣的 DAG,那麼我們實際上在做的事情會是:

  • 在 2023/01/02 的時候,執行這個 dag,蒐集 2023/01/01 ~ 2023/01/02 的資料

  • 在 2023/01/03 的時候,執行這個 dag,蒐集 2023/01/02 ~ 2023/01/03 的資料

  • 在 2023/01/04 的時候,執行這個 dag,蒐集 2023/01/03 ~ 2023/01/04 的資料

(P.S. 我們必須等到 2 號的最一開始,也就是 1/1 過完的時候,才能搜集 01/01 ~ 01/02 的資料)

而已「在 2023/01/02 的時候,蒐集 2023/01/01 ~ 2023/01/02 的資料」這個 dag run 為例子,他的 execution_date 就是 2023/01/01,代表資料搜集區間的開始時間範圍,而不是這個 dag 實際執行的時間。而這個 dag 實際實際執行的時間則可以透過 next_execution_date 來得到

Usage

從上述的例子裡面我們也可以發現,如果你希望你的 daily dag 在 2023/01/01 就開始執行,那你應該:

schedule_interval="@daily",
start_date=dt.datetime(2022, 12, 31) #2023/01/01 - sechedule_interval

同理如果這是一個 hourly_dag,但也要在 2023/01/01 就執行的話:

schedule_interval="@hourly",
start_date=dt.datetime(2022, 12, 31, 23, 0, 0) #2023/01/01 - sechedule_interval

而由上面兩個例子可以看到,真實執行的時間都是 2023/01/01 但是因為 schedule_interval 的設定不同,execution_date 會是不一樣的。因此要得到這個 DAG 真正被執行的時間(也就是 2023/01/01)則需要透過 next_execution_date 來得到。

In the end

  1. 在新版的 airflow 官方建議用 logical_date 來取代命名容易讓人誤會的 execution_date

  2. 我想 execution_date 的意義會認人誤會,一部分的原因是因為我們常常不只用 airflow 來處理 ETL,而是使用他來管理各式 cronjob,因此才會用任務的執行時間來解讀他,而不是用資料蒐集的角度。

Acknowledge

  1. Photo by Estée Janssens on Unsplash