fix(airflow): fiabilise l'import horaire de la Mock API
Airflow / Construction de l'image (push) Successful in 1m4s
Backend / Analyse statique de sécurité (push) Successful in 7s
Backend / Tests exigeant une base (push) Failing after 4m55s
Airflow / Lint et intégrité des DAGs (push) Successful in 9m49s
Backend / Lint, typage et tests (push) Successful in 10m12s
Backend / Audit des dépendances (push) Successful in 9m36s
SonarQube / build-front (push) Successful in 9m35s
SonarQube / test-ml (push) Failing after 5m37s
SonarQube / build-back (push) Successful in 9m46s
SonarQube / test-front (push) Failing after 5m4s
SonarQube / test-back (push) Failing after 5m9s
SonarQube / SonarQube (push) Skipped
Airflow / Construction de l'image (push) Successful in 1m4s
Backend / Analyse statique de sécurité (push) Successful in 7s
Backend / Tests exigeant une base (push) Failing after 4m55s
Airflow / Lint et intégrité des DAGs (push) Successful in 9m49s
Backend / Lint, typage et tests (push) Successful in 10m12s
Backend / Audit des dépendances (push) Successful in 9m36s
SonarQube / build-front (push) Successful in 9m35s
SonarQube / test-ml (push) Failing after 5m37s
SonarQube / build-back (push) Successful in 9m46s
SonarQube / test-front (push) Failing after 5m4s
SonarQube / test-back (push) Failing after 5m9s
SonarQube / SonarQube (push) Skipped
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""DAG d'import périodique des données de l'API Mock EnerVision (issue #15).
|
||||
|
||||
Orchestre le pipeline existant `app.etl.mock_api_import` sans dupliquer sa logique ETL.
|
||||
Chaque exécution traite l'intervalle horaire Airflow précédent.
|
||||
Chaque exécution traite l'heure précédant son déclenchement.
|
||||
|
||||
Le pipeline backend reste responsable de la validation, de la normalisation, du suivi de la
|
||||
qualité, de l'idempotence et du chargement dans PostgreSQL/TimescaleDB.
|
||||
@@ -13,12 +13,14 @@ from datetime import datetime, timedelta
|
||||
|
||||
from airflow.providers.standard.operators.bash import BashOperator
|
||||
from airflow.sdk import DAG
|
||||
from airflow.timetables.trigger import CronTriggerTimetable
|
||||
|
||||
# Le backend possède son propre environnement uv dans l'image Airflow (ADR 0008).
|
||||
COMMANDE_BACKEND = "cd /opt/backend && env -u VIRTUAL_ENV uv run --no-sync python -m"
|
||||
|
||||
# L'API et le pipeline backend plafonnent une réponse à 1 000 lectures par site.
|
||||
LIMITE_LECTURES = 60
|
||||
# Le pipeline backend et l'API acceptent au maximum 1 000 lectures par site.
|
||||
# Cette marge évite de perdre silencieusement une lecture si une heure en contient plus de 60.
|
||||
LIMITE_LECTURES = 1000
|
||||
|
||||
# Deux reprises donnent trois tentatives au total. Même dans le pire cas, l'exécution reste
|
||||
# inférieure au pas horaire du DAG.
|
||||
@@ -26,10 +28,19 @@ NOMBRE_REPRISES = 2
|
||||
DELAI_ENTRE_REPRISES = timedelta(minutes=2)
|
||||
PLAFOND_PAR_TENTATIVE = timedelta(minutes=10)
|
||||
|
||||
# L'intervalle est déclaré explicitement pour ne pas dépendre de la valeur du paramètre Airflow
|
||||
# `create_cron_data_intervals`. Le déclenchement à :45 laisse quinze minutes avant `ml_score`,
|
||||
# exécuté à l'heure pile, puis avant `alertes`, exécuté à :15.
|
||||
PLANIFICATION = CronTriggerTimetable(
|
||||
"45 * * * *",
|
||||
timezone="UTC",
|
||||
interval=timedelta(hours=1),
|
||||
)
|
||||
|
||||
with DAG(
|
||||
dag_id="mock_api_import",
|
||||
description="Importe chaque heure les données de l'API Mock dans site et reading.",
|
||||
schedule="@hourly",
|
||||
schedule=PLANIFICATION,
|
||||
start_date=datetime(2026, 1, 1),
|
||||
catchup=False,
|
||||
# Deux exécutions simultanées pourraient demander et traiter le même intervalle.
|
||||
@@ -40,8 +51,8 @@ with DAG(
|
||||
task_id="import_mock_api",
|
||||
bash_command=(
|
||||
f"{COMMANDE_BACKEND} app.etl.mock_api_import "
|
||||
'--start-time "{{ data_interval_start.isoformat() }}" '
|
||||
'--end-time "{{ data_interval_end.isoformat() }}" '
|
||||
"--start-time \"{{ data_interval_start.strftime('%Y-%m-%dT%H:%M:%S') }}\" "
|
||||
"--end-time \"{{ data_interval_end.strftime('%Y-%m-%dT%H:%M:%S') }}\" "
|
||||
f"--limit {LIMITE_LECTURES}"
|
||||
),
|
||||
retries=NOMBRE_REPRISES,
|
||||
|
||||
Reference in New Issue
Block a user