「動的タスク」に関する他の質問は、スケジュールまたは設計時にDAGの動的構築に対処しているようです。実行中にDAGにタスクを動的に追加することに興味があります。
from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator
from airflow.operators.python_operator import PythonOperator
from datetime import datetime
dag = DAG('test_dag', description='a test',
schedule_interval='0 0 * * *',
start_date=datetime(2018, 1, 1),
catchup=False)
def make_tasks():
du1 = DummyOperator(task_id='dummy1', dag=dag)
du2 = DummyOperator(task_id='dummy2', dag=dag)
du3 = DummyOperator(task_id='dummy3', dag=dag)
du1 >> du2 >> du3
p = PythonOperator(
task_id='python_operator',
dag=dag,
python_callable=make_tasks)
この素朴な実装は機能していないようです-ダミータスクがUIに表示されることはありません。
実行中に新しいオペレーターをDAGに追加する正しい方法は何ですか?出来ますか?
実行中にDAGを変更することはできません(多くの作業がなければ)。
dag = DAG(...
は、スケジューラによってループで取得されます。タスクインスタンス'python_operator'
初期化。そのタスクインスタンスは、Dag Runでスケジュールされ、ワーカーまたはエグゼキューターによって実行されます。 Airflow DBのDAGモデルはスケジューラーによってのみ更新されるため、これらの追加されたダミータスクはDAGに保持されず、実行のスケジュールも設定されません。労働者が退出すると、それらは忘れられます。モデルの永続化と更新に関するすべてのコードをスケジューラーからコピーしない限り...ただし、スケジューラーが解析のためにDAGファイルに次回アクセスしたときに、元に戻されます。解析するDAGファイルがあります。
Airflowは実際には、各DAGが実行間でほぼ同じレイアウトに留まることを望んでいます。また、DAGファイルを常に再読み込み/解析したいと考えています。したがって、DAGファイルを作成して、実行ごとに一部の外部データに基づいてタスクを動的に決定することもできますが(DBルックアップのようなネットワークI/Oではなく、ファイルまたはpycモジュールにキャッシュされることが望ましいです)、スケジューリングループ全体の速度が低下します。 all DAGの場合)グラフとツリービューがすべて混乱し、スケジューラの解析がそのルックアップによってさらに課税されるため、これは良い計画ではありません。
呼び出し可能オブジェクトに各タスクを実行させることができます…
def make_tasks(context):
du1 = DummyOperator(task_id='dummy1', dag=dag)
du2 = DummyOperator(task_id='dummy2', dag=dag)
du3 = DummyOperator(task_id='dummy3', dag=dag)
du1.execute(context)
du2.execute(context)
du3.execute(context)
p = PythonOperator(
provides_context=true,
しかし、それは順次的であり、pythonを使用してそれらを並列にする方法(futureを使用しますか?)を考え出す必要があります。例外が発生すると、タスク全体が失敗します。また、1つのエグゼキュータにバインドされていますまたは、気流のタスク配分(kubernetes、mesos、celery)を使用しないワーカー。
これを処理するもう1つの方法は、固定数のタスク(最大数)を追加し、呼び出し可能オブジェクトを使用して、不要なタスクを短絡するか、タスクごとにxcomを使用して引数をプッシュし、実行時の動作を変更することです。 DAGは変更しません。
動的に構造化されたDAGを作成するのと同じ課題があるので、ここで誰もが行ったすべての作業に感謝します。私はその設計に対してソフトウェアを使用しないように十分な間違いをしました。 UIで実行全体を検査して拡大および縮小できない場合は、基本的にエアフロー機能を使用します。これが、とにかくそれを使用する主な理由です。関数内にマルチプロセッシングコードを記述して、それで処理を完了することもできます。
私の解決策は、redisロックなどのリソースマネージャーを使用し、実行する方法などのデータをこのリソースマネージャーに書き込むDAGを用意することです。また、リソースマネージャーをポーリングする特定の間隔で実行される別のDAGがあり、実行前にロックして、終了時に削除します。この方法では、仕様が私のニーズを正確に満たしていない場合でも、少なくとも予想どおりにエアフローを使用します。問題をより明確なチャンクに分類します。ソリューションは独創的ですが、それらは設計に反しており、開発者によってテストされていません。具体的には、固定された構造化ワークフローがあると言います。コアエアフローコードを書き直して自分でテストしない限り、テストされておらずデザインに反するコードを回避することはできません。私のソリューションはロックの複雑さをもたらすことを理解していますが、少なくともその境界を知っています。
コードサンプルについては、DAGにタスクを登録する関数を呼び出すことはありません。
ある種の動的タスクを作成するには、ある状態に応じて何かを行う単一の演算子を使用するか、またはShortCircuitOperatorを使用して、状態に応じてスキップできる少数の演算子を使用できます。