私は主に、ETL /入札データ関連のジョブにエアフローが使用されているのを見ます。ユーザーアクションが一連の依存タスクを将来的にトリガーするビジネスワークフローに使用しようとしています。これらのタスクの一部は、他の特定のユーザーアクションに基づいてクリア(削除)する必要がある場合があります。これを処理する最良の方法は、動的なタスクIDを使用することだと思いました。 Airflowが動的dag idをサポートしていることを読みました。だから、コマンドラインパラメータとしてDAG IDとタスクIDを取る単純なpythonスクリプトを作成しました。しかし、動作させるために問題に直面しています。それはdag_idが見つかりませんエラーを与えます。これを試しましたか?python(python tmp.py 820 2016-08-24T22:50:00)としてコマンドラインで実行するスクリプトのコード(tmp.pyと呼びます):
from __future__ import print_function
import os
import sys
import shutil
from datetime import date, datetime, timedelta
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
execution = '2016-08-24T22:20:00'
if len(sys.argv) > 2 :
dagid = sys.argv[1]
taskid = 'Activate' + sys.argv[1]
execution = sys.argv[2]
else:
dagid = 'DAGObjectId'
taskid = 'Activate'
default_args = {'owner' : 'airflow', 'depends_on_past': False, 'start_date':date.today(), 'email': ['[email protected]'], 'email_on_failure': False, 'email_on_retry': False, 'retries': 1}
dag = DAG(dag_id = dagid,
default_args=default_args,
schedule_interval='@once',
)
globals()[dagid] = dag
task1 = BashOperator(
task_id = taskid,
bash_command='ls -l',
dag=dag)
fakeTask = BashOperator(
task_id = 'fakeTask',
bash_command='sleep 5',
retries = 3,
dag=dag)
task1.set_upstream(fakeTask)
airflowcmd = "airflow run " + dagid + " " + taskid + " " + execution
print("airflowcmd = " + airflowcmd)
os.system(airflowcmd)
多くの試行錯誤の後、私はこれを理解することができました。うまくいけば、それが誰かを助けるでしょう。仕組みは次のとおりです。テンプレートを介して動的にdags/taskを生成するには、イテレータまたは外部ソース(ファイル/データベーステーブル)が必要です。 DAGとタスク名を静的に保ち、DAGを動的に割り当てるだけで、DAGとタスク名を区別できます。このpythonスクリプトをdagsフォルダーに配置します。エアフロースケジューラーを起動すると、すべてのハートビートでこのスクリプトが実行され、DAGがデータベースのdagテーブルに書き込まれます。スケジューラはすでにスキップされます。スケジューラは個々のDAGのスケジュールを調べて、どのDAGが実行準備ができているかを判断します。DAGが実行準備ができている場合、それを実行してステータスを更新します。サンプルコードを次に示します。
from airflow.operators import PythonOperator
from airflow.operators import BashOperator
from airflow.models import DAG
from datetime import datetime, timedelta
import sys
import time
dagid = 'DA' + str(int(time.time()))
taskid = 'TA' + str(int(time.time()))
input_file = '/home/directory/airflow/textfile_for_dagids_and_schedule'
def my_sleeping_function(random_base):
'''This is a function that will run within the DAG execution'''
time.sleep(random_base)
def_args = {
'owner': 'airflow',
'depends_on_past': False,
'start_date': datetime.now(), 'email_on_failure': False,
'retries': 1, 'retry_delay': timedelta(minutes=2)
}
with open(input_file,'r') as f:
for line in f:
args = line.strip().split(',')
if len(args) < 6:
continue
dagid = 'DAA' + args[0]
taskid = 'TAA' + args[0]
yyyy = int(args[1])
mm = int(args[2])
dd = int(args[3])
hh = int(args[4])
mins = int(args[5])
ss = int(args[6])
dag = DAG(
dag_id=dagid, default_args=def_args,
schedule_interval='@once', start_date=datetime(yyyy,mm,dd,hh,mins,ss)
)
myBashTask = BashOperator(
task_id=taskid,
bash_command='python /home/directory/airflow/sendemail.py',
dag=dag)
task2id = taskid + '-X'
task_sleep = PythonOperator(
task_id=task2id,
python_callable=my_sleeping_function,
op_kwargs={'random_base': 10},
dag=dag)
task_sleep.set_upstream(myBashTask)
f.close()
Airflowは、グローバル名前空間にDAGオブジェクトを含むモジュールを[sic] DAGS_FOLDERで検索し、見つかったオブジェクトをDagBagに追加します。これを知っている必要があるのは、グローバル名前空間で変数を動的に割り当てる方法です。これは、単純な辞書のように動作する標準ライブラリのglobals()関数を使用してpython.
for i in range(10): dag_id = 'foo_{}'.format(i) globals()[dag_id] = DAG(dag_id) # or better, call a function that returns a DAG object!