Fastodata / Onboarding

Module d'onboarding — Airflow

Contenu pédagogique produit par Bill (QA). Destiné à onboarding.fastodata.com.
Public : ingénieur data avec Python OK. Format : théorie d'abord → exercices → quiz corrigé.
Contexte équipe : orchestration de pipelines data (alternative/complément à Kestra), souvent au-dessus de BigQuery/dbt.
Durée estimée : ~3-4 h.


Objectifs pédagogiques

À la fin, l'apprenant sait :

  1. Expliquer le rôle d'Airflow (orchestrateur de workflows) et son modèle DAG.
  2. Écrire un DAG avec la TaskFlow API et des opérateurs.
  3. Comprendre scheduling, schedule, catchup, backfill, intervalles.
  4. Gérer dépendances, retries, SLA, et passage de données (XCom).
  5. Distinguer Operators / Sensors / Hooks, et utiliser les connexions/variables.
  6. Lire l'UI, débugger une tâche, éviter les pièges classiques.

Module 1 — Le modèle mental Airflow

Airflow orchestre : il décide quoi lancer, quand, dans quel ordre, et que faire en cas d'échec. Il n'est pas un moteur de calcul — comme dbt délègue à BigQuery, Airflow délègue le travail réel aux systèmes cibles (BigQuery, Spark, conteneurs, scripts).

⚠️ Piège central : Airflow est orienté intervalles de données, pas « maintenant ». Un DAG @daily qui tourne le 2 traite la journée du 1er (data_interval_start=1, end=2). C'est la source n°1 de confusion.


Module 2 — Écrire un DAG (TaskFlow API)

Style moderne (Airflow 2+), pythonique :

from airflow.decorators import dag, task
import pendulum

@dag(
    schedule="@daily",
    start_date=pendulum.datetime(2024, 1, 1, tz="UTC"),
    catchup=False,
    tags=["ventes"],
)
def pipeline_ventes():

    @task
    def extract() -> list[dict]:
        return [{"id": 1, "amount": 100}]

    @task
    def transform(rows: list[dict]) -> int:
        return sum(r["amount"] for r in rows)

    @task
    def load(total: int):
        print(f"total chargé : {total}")

    load(transform(extract()))   # les dépendances se déduisent des appels

pipeline_ventes()

Style classique (Operators) — toujours courant :

from airflow.operators.bash import BashOperator
t1 = BashOperator(task_id="dump", bash_command="echo go")
t2 = BashOperator(task_id="post", bash_command="echo done")
t1 >> t2     # t1 puis t2  (équivalent : t2 << t1)

a >> b = a avant b. [a, b] >> c = c attend a et b.


Module 3 — Scheduling, catchup, backfill

Variables d'intervalle utiles dans les templates : {{ data_interval_start }}, {{ data_interval_end }}, {{ ds }} (date logique YYYY-MM-DD).


Module 4 — Dépendances, retries, SLA, XCom

@task(retries=3, retry_delay=pendulum.duration(minutes=5))
def fragile(): ...

Module 5 — Operators, Sensors, Hooks, Connections


Module 6 — UI, debug & bonnes pratiques


Exercices

  1. Écris un DAG @hourly, catchup=False, qui : (a) extract une liste, (b) transform en agrégat, (c) load. En TaskFlow API.
  2. Ajoute 3 retries + 2 min de delay sur la tâche extract, et un execution_timeout de 10 min sur transform.
  3. Un DAG quotidien doit traiter la veille. Quelles variables de template utilises-tu pour borner la requête sur le bon intervalle ?
  4. Tu déploies un DAG avec start_date il y a 6 mois. Que se passe-t-il avec catchup=True ? Comment l'éviter ?
  5. Une tâche de notification doit s'exécuter même si une tâche amont a échoué. Quelle trigger_rule ?

Quiz final corrigé

Q1. Airflow exécute-t-il le calcul lui-même ?
→ Non. C'est un orchestrateur ; il délègue le travail aux systèmes cibles (BigQuery, Spark, conteneurs…).

Q2. Un DAG @daily start_date=1er janv : quand tourne le run du 1er janvier, et quel intervalle traite-t-il ?
→ Il se déclenche à la fin de l'intervalle (≈ 2 janv 00:00) et traite la journée du 1er (data_interval_start=1er, end=2).

Q3. Différence catchup=True vs False ?
True rattrape tous les intervalles manqués depuis start_date (risque de centaines de runs). False ne lance que le plus récent. Défaut conseillé : False.

Q4. À quoi sert XCom, et qu'est-ce qu'on n'y met PAS ?
→ Passer de petites valeurs/métadonnées entre tâches. On n'y met pas de gros volumes (ça va en base/stockage objet).

Q5. Operator vs Sensor vs Hook ?
→ Operator = fait une action. Sensor = attend une condition (préférer reschedule). Hook = client bas-niveau vers un système externe, utilisé par les Operators.

Q6. Pourquoi éviter le code lourd au top-level d'un fichier DAG ?
→ Le scheduler parse les fichiers en boucle ; tout calcul/appel réseau à l'import ralentit/instabilise le parsing. Le travail doit être dans les tâches.

Q7. Que veut dire « DAG idempotent » et pourquoi c'est crucial ?
→ Rejouer un même intervalle produit le même résultat sans doublon. Crucial car retries/backfills relancent des intervalles — sinon données dupliquées.


Pour aller plus loin

→ BigQuery → Git & CI → dbt (data build tool) → Kestra