Airflow 裡面的 start_date
、execution_date
對不熟悉的人說是很反直覺的。
TLDR
在這篇文章中我會解釋為什麼 airflow 的 execution_date 跟我們想的不一樣
start_date
,schedule_interval
,execution_date
,next_execution_date
的用法
在展開對這三個 term 的描述之前,請先記得我們在使用 airflow 的時候,如官方所建議的,都該使用 UTC+0 作為時區。
Why
start_date
、execution_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
在新版的 airflow 官方建議用
logical_date
來取代命名容易讓人誤會的execution_date
我想
execution_date
的意義會認人誤會,一部分的原因是因為我們常常不只用 airflow 來處理 ETL,而是使用他來管理各式 cronjob,因此才會用任務的執行時間來解讀他,而不是用資料蒐集的角度。
Acknowledge
- Photo by Estée Janssens on Unsplash