web-dev-qa-db-ja.com

PythonでDAGを使用してAWS athenaテーブルで新しいパーティション/データが使用可能な場合にのみAirflowタスクをトリガーするにはどうすればよいですか?

私は以下のようなシーンを持っています:

  1. トリガーTask 1およびTask 2ソーステーブル(Athena)で新しいデータを利用できる場合のみ。 Task1とTask2のトリガーは、新しいデータパーティションが1日に発生したときに発生します。
  2. 引き金 Task 3完了時のみTask 1およびTask 2
  3. 引き金 Task 4完了のみTask 3

enter image description here

マイコード

from airflow import DAG

from airflow.contrib.sensors.aws_glue_catalog_partition_sensor import AwsGlueCatalogPartitionSensor
from datetime import datetime, timedelta

from airflow.operators.postgres_operator import PostgresOperator
from utils import FAILURE_EMAILS

yesterday = datetime.combine(datetime.today() - timedelta(1), datetime.min.time())

default_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': yesterday,
    'email': FAILURE_EMAILS,
    'email_on_failure': False,
    'email_on_retry': False,
    'retries': 1,
    'retry_delay': timedelta(minutes=5)
}

dag = DAG('Trigger_Job', default_args=default_args, schedule_interval='@daily')

Athena_Trigger_for_Task1 = AwsGlueCatalogPartitionSensor(
    task_id='athena_wait_for_Task1_partition_exists',
    database_name='DB',
    table_name='Table1',
    expression='load_date={{ ds_nodash }}',
    timeout=60,
    dag=dag)

Athena_Trigger_for_Task2 = AwsGlueCatalogPartitionSensor(
    task_id='athena_wait_for_Task2_partition_exists',
    database_name='DB',
    table_name='Table2',
    expression='load_date={{ ds_nodash }}',
    timeout=60,
    dag=dag)

execute_Task1 = PostgresOperator(
    task_id='Task1',
    postgres_conn_id='REDSHIFT_CONN',
    sql="/sql/flow/Task1.sql",
    params={'limit': '50'},
    trigger_rule='all_success',
    dag=dag
)

execute_Task2 = PostgresOperator(
    task_id='Task2',
    postgres_conn_id='REDSHIFT_CONN',
    sql="/sql/flow/Task2.sql",
    params={'limit': '50'},
    trigger_rule='all_success',
    dag=dag
)



execute_Task3 = PostgresOperator(
    task_id='Task3',
    postgres_conn_id='REDSHIFT_CONN',
    sql="/sql/flow/Task3.sql",
    params={'limit': '50'},
    trigger_rule='all_success',
    dag=dag
)

execute_Task4 = PostgresOperator(
    task_id='Task4',
    postgres_conn_id='REDSHIFT_CONN',
    sql="/sql/flow/Task4",
    params={'limit': '50'},
    dag=dag
)



execute_Task1.set_upstream(Athena_Trigger_for_Task1)
execute_Task2.set_upstream(Athena_Trigger_for_Task2)

execute_Task3.set_upstream(execute_Task1)
execute_Task3.set_upstream(execute_Task2)

execute_Task4.set_upstream(execute_Task3)

それを達成するための最良の最適な方法は何ですか?

4
pankaj

あなたの質問は2つの主要な問題に対処していると思います。

  1. _schedule_interval_を明示的に設定するのを忘れているため、@ dailyは予期しないものを設定しています。
  2. 実行を完了するために外部イベントに依存しているときに、DAGの実行を適切にトリガーして再試行する方法

短い答え:cronジョブ形式を使用してschedule_intervalを明示的に設定し、センサーオペレーターを使用して時々チェックします

_default_args={
        'retries': (endtime - starttime)*60/poke_time
}
dag = DAG('Trigger_Job', default_args=default_args, schedule_interval='0 10 * * *')
Athena_Trigger_for_Task1 = AwsGlueCatalogPartitionSensor(
     ....
    poke_time= 60*5 #<---- set a poke_time in seconds
    dag=dag)
_

ここで、startimeは毎日のタスクを開始する時間、endtimeは、イベントに失敗のフラグを付ける前にイベントが行われたかどうかを確認する必要がある最後の時間で、_poke_time_は_sensor_operator_がイベントが発生したかどうかを確認する間隔。

cronジョブに明示的に対処する方法dagを_@daily_のように設定するときはいつでもあなたがした:

_dag = DAG('Trigger_Job', default_args=default_args, schedule_interval='@daily')
_

docs から、実際にやっていることがわかります:_@daily - Run once a day at midnight_

これは、タイムアウトエラーが発生する理由になり、_'retries': 1_と'retry_delay': timedelta(minutes=5)を設定したため、5分後に失敗します。したがって、真夜中にDAGを実行しようとすると失敗します。 5分後に再び再試行して失敗するため、失敗としてフラグが立てられます。

したがって、基本的に@daily runは次の暗黙のcronジョブを設定します。

_@daily -> Run once a day at midnight -> 0 0 * * *
_

Cronジョブの形式は以下の形式で、「すべて」と言いたいときは常に値を_*_に設定します。

_Minute Hour Day_of_Month Month Day_of_Week_

つまり、@ dailyは基本的にこれを次の間隔で実行すると言っています:すべてのdays_of_weekのすべての月のすべてのdays_of_monthの0分0

したがって、ケースは次の間隔で実行されます:すべてのdays_of_weekのall_monthsのすべてのdays_of_monthの分0時間10。これはcronジョブ形式で次のように変換されます。

_0 10 * * *
_

外部イベントに依存して実行を完了するときに、DAGの実行をトリガーして再試行する方法

  1. コマンド_airflow trigger_dag_を使用して、外部イベントからエアフローのダグをトリガーできます。これは、何らかの方法でラムダ関数をトリガーできる場合に可能です/ pythonスクリプトでairflowインスタンスをターゲットにする.

  2. 外部でDAGをトリガーできない場合は、OPのようなセンサーオペレーターを使用して、poke_timeをそれに設定し、適切な再試行回数を設定します。