feat(etl): ordonnance la détection d'alertes et les recommandations par un DAG Airflow
Le DAG `alertes` enchaîne `app.detection.internal_alerts` puis `app.cli generate-recommendations`, à la quinzième minute de chaque heure. Le décalage laisse finir `ml_score`, qui écrit à l'heure pile les prédictions dont la règle `anomaly` a besoin, sans créer de dépendance entre les deux DAGs : quatre règles de détection sur cinq ne touchent pas au modèle, et un modèle jamais entraîné ne doit pas priver le parc de ses alertes. L'image Airflow porte un second environnement uv, `/opt/backend/.venv`, puisque la logique vit dans le backend (ADR 0006) et qu'aucune route HTTP ne l'expose. Le `UV_PROJECT_ENVIRONMENT` global hérité de l'issue #115 disparaît : il vaut pour tous les projets, donc `uv run` depuis `/opt/ml` résolvait le venv du backend. uv prend `<projet>/.venv` par défaut, se placer dans le dossier suffit. La CI vérifie maintenant que les deux environnements s'importent sans réseau. Le conteneur reçoit `DATABASE_URL` en asyncpg et une `APP_SECRET_KEY` distincte de celle de l'API, alimentée par `AIRFLOW_APP_SECRET_KEY` : la détection ne signe aucun jeton, et Airflow permet d'exécuter du code depuis son interface.
This commit is contained in:
@@ -38,3 +38,8 @@ AIRFLOW_ADMIN_USERNAME=admin
|
||||
# comptes `app_user` d'EnerVision.
|
||||
AIRFLOW_ADMIN_PASSWORD=change_me
|
||||
AIRFLOW_ADMIN_EMAIL=admin@enervision.fr
|
||||
# `APP_SECRET_KEY` du backend, que le DAG `alertes` lance en sous-processus. Distincte de
|
||||
# celle de l'API : la détection ne signe aucun jeton, et Airflow exécute du code depuis son
|
||||
# interface (cf. ADR 0008). Générer la vôtre :
|
||||
# python -c "import secrets; print(secrets.token_urlsafe(48))"
|
||||
AIRFLOW_APP_SECRET_KEY=change_me
|
||||
|
||||
Reference in New Issue
Block a user