Come attivare un'attività Airflow solo quando nuove partizioni / dati sono disponibili nella tabella AWS athena usando DAG in Python?


9

Ho uno scenerio come un sotto:

  1. Attiva a Task 1e Task 2solo quando sono disponibili nuovi dati nella tabella di origine (Athena). Il trigger per Task1 e Task2 dovrebbe avvenire quando una nuova partizione di dati in un giorno.
  2. Trigger Task 3solo al completamento di Task 1eTask 2
  3. Attiva Task 4solo il completamento diTask 3

inserisci qui la descrizione dell'immagine

Il mio codice

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)

Qual è il modo migliore ottimale per raggiungerlo?


hai problemi con questa soluzione?
Bernardo stearns è tornato il

@ Bernardostearnsreisen, a volte Task1e Task2va in loop. Per me i dati vengono caricati nella tabella di origine Athena alle 10 CET.
pankaj,

facendo un ciclo, intendi, il flusso d'aria riprova Task1 e Task2 molte volte fino a quando non ha successo?
Bernardo stearns è tornato il

@Bernardostearnsreisen, yup esattamente
pankaj

1
@Bernardostearnsreisen, non sapevo come assegnare la taglia :)
pankaj

Risposte:


1

Credo che la tua domanda affronti due problemi principali:

  1. dimenticando di configurare schedule_intervalin modo esplicito così @daily sta configurando qualcosa che non ti aspetti.
  2. Come innescare e riprovare correttamente l'esecuzione del dag quando si dipende da un evento esterno per completare l'esecuzione

la risposta breve: imposta esplicitamente il tuo schedule_interval con un formato cron job e usa gli operatori dei sensori per controllare di tanto in tanto

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)

dov'è a startimeche ora inizierà l'attività quotidiana, endtimequal è l'ultima ora del giorno in cui dovresti controllare se un evento è stato fatto prima che la segnalazione sia fallita ed poke_timeè l'intervallo sensor_operatorche controllerai se si è verificato l'evento.

Come affrontare esplicitamente il lavoro cron ogni volta che imposti il ​​tuo dag@dailycome hai fatto:

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

dai documenti , puoi vedere che stai effettivamente facendo: @daily - Run once a day at midnight

Che ora ha senso perché stai ricevendo un errore di timeout e non riesce dopo 5 minuti perché hai impostato 'retries': 1e 'retry_delay': timedelta(minutes=5). Quindi prova a eseguire il dag a mezzanotte, fallisce. riprova 5 minuti dopo e fallisce di nuovo, quindi viene contrassegnato come non riuscito.

Quindi, in pratica, @daily run sta impostando un cron job implicito di:

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

Il formato cron job è del formato seguente e si imposta il valore su *ogni volta che si desidera dire "all".

Minute Hour Day_of_Month Month Day_of_Week

Quindi @daily dice sostanzialmente di eseguirlo ogni: minuto 0 ora 0 di tutti i giorni_di_mese di tutti i mesi di tutti i giorni_di_settimana

Quindi il tuo caso viene eseguito ogni: minuto 0 ora 10 di tutti i giorni_di_mesi di tutti i mesi di tutti i giorni_di_settimana. Questo si traduce in formato cron job in:

0 10 * * *

Come innescare e riprovare correttamente l'esecuzione del dag quando si dipende da un evento esterno per completare l'esecuzione

  1. si potrebbe innescare un dag in flusso d'aria da un evento esterno utilizzando il comando airflow trigger_dag. ciò sarebbe possibile se in qualche modo si potesse attivare uno script lambda / python per indirizzare l'istanza del flusso d'aria.

  2. Se non è possibile attivare il dag esternamente, utilizzare un operatore sensore come OP, impostare un poke_time su di esso e impostare un numero elevato di tentativi ragionevole.


Grazie per questo. Inoltre, se voglio attivare le attività in base all'evento piuttosto che al tempo, ovvero non appena sarà disponibile una nuova partizione di dati nella prossima attività di origine `AWS Athena Tables`. Quindi come posso programmare. Il mio codice attuale è abbastanza adatto.
pankaj,

@pankaj, vedo solo due alternative. Non so molto di aws athena, ma potresti attivare un dag nel flusso d'aria da un evento esterno usando il comando airflow trigger_dag. questo sarebbe possibile se in qualche modo si potesse attivare uno script lambda / python per indirizzare l'istanza del flusso d'aria.
Bernardo stearns è tornato il

l'altra alternativa è più o meno ciò che stai facendo, perché non hai un trigger basato su eventi, devi controllare periodicamente se questo evento si è verificato. Quindi, usando questa soluzione attuale, verrebbe impostato un cron job per un intervallo di ore eseguendo il dag in un'alta frequenza di minuti ... molti falliranno ma sarà in grado di catturare abbastanza rapidamente dopo l'evento
Bernardo stearns reisen

@Bernado, ho scoperto il pacchetto in Airflow chiamato AwsGlueCatalogPartitionSensorinsieme al comando airflow {{ds_nodash}}per le uscite della partizione. La mia domanda quindi come programmare questo.
pankaj,

@Benado, puoi dare un'occhiata al mio codice in cui ho implementato il controllo sopra menzionato e dare i tuoi input
pankaj
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.