PythonでDAGを使用してAWS athenaテーブルで新しいパーティション/データが利用可能な場合にのみAirflowタスクをトリガーする方法


9

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

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

ここに画像の説明を入力してください

私のコード

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)

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


この解決策で何か問題がありますか?
ベルナルドスターンズは

Bernardostearnsreisen @、時にはTask1およびTask2ループに入ります。私にとって、データはAthenaソーステーブルの10 AM CETに読み込まれます。
pankaj

つまり、ループが成功するまで、エアフローはTask1とTask2を何度も再試行します。
ベルナルドスターンズは

@Bernardostearnsreisen、うん、正確に
pankaj

1
@Bernardostearnsreisen、私は賞金を授与する方法を知り
ませんでした

回答:


1

あなたの質問は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ジョブに明示的に対処する方法 あなたがあなたの@dailyようにあなたのDAGを設定しているときはいつでも:

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

ドキュメントから、あなたが実際にやっていることがわかります: @daily - Run once a day at midnight

これは、タイムアウトエラーが発生する理由になり、5分後に設定したため失敗します。 'retries': 1した'retry_delay': timedelta(minutes=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をそれに設定し、適切な再試行回数を設定します。


これをありがとう。また、時間ではなくイベントに基づいてタスクをトリガーする場合、つまり、ソース `AWS Athena Tables`で新しいデータパーティションが利用可能になるとすぐに、次のタスクがトリガーされます。次に、どのようにスケジュールしますか。現在のコードで十分ですか?
pankaj

@pankaj、選択肢は2つしかありません。aws athenaについてはよく知りませんが、コマンドを使用して、外部イベントから気流のダグをトリガーできますairflow trigger_dag。これは、何らかの方法でラムダ関数/ Pythonスクリプトをトリガーしてairflowインスタンスをターゲットにできる場合に可能です。
ベルナルドスターンズ

イベントベースのトリガーがないので、もう1つの代替案はあなたがやっていることです。このイベントが発生したかどうかを定期的にチェックする必要があります。したがって、この現在のソリューションを使用すると、時間の範囲でcronジョブが設定され、高頻度で分が実行されます。多くの場合は失敗しますが、イベントの発生後はかなり迅速にキャッチできます
Bernardo stearns reisen

@Bernado、パーティション出口のairflow AwsGlueCatalogPartitionSensorコマンドとともに呼び出されるAirflowのパッケージを見つけました{{ds_nodash}}。私の質問は、これをどのようにスケジュールするかです。
pankaj

@ベナド、上記のチェックを実装した私のコードを見て、入力を提供できますか
pankaj
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.