[EF-05] Alertes de la zone argent vers la zone or #168
Labels
No labels
Compat/Breaking
EC01
EC02
EC03
EC04
EC05
EC06
Kind/BDD
Kind/Back
Kind/Bug
Kind/CICD
Kind/Cloud
Kind/Contenu
Kind/Data
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Front
Kind/IA
Kind/Infra
Kind/Monitoring
Kind/Security
Kind/Testing
Portée/Post-jury
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
ops/alerte
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
g2/enervision#168
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Exigence couverte
EF-05, ENF-07
Épreuve servie
EC05 · Data, ETL et BI
Charge estimée
1 j.h
Ce qu'on veut obtenir
Le #165 fait entrer les alertes de la source en zone argent. Ce ticket termine le chemin :
silver.alerte→gold/table=alerte→public.alerte, la seule couche que l'API et Grafana lisent.Sans lui,
public.alertereste vide, et l'écran Qualité comme le pavé « alertes ouvertes » de l'écran Parc affichent des fixtures le jour du jury. Les PR #155 et #156 en dépendent.Dépend du #165, qui doit être fusionné avant.
Critères d'acceptation
gold/table=alerte/dt=AAAA-MM-JJest écrite depuis la partition argent du même jour, une ligne par alerte.public.alerteest chargée en upsert ; rejouer la journée ne crée pas de doublon, la clé(site_id, horodatage, type, source)y suffit.source = 'api_simulation', jamais'regle': mélanger les deux interdirait de mesurer nos règles contre le repère de calibrage (migration 0012).taux_de_chargeest calculé depuis la capacité que la ligne argent porte déjà, sans jointure au référentiel.gold.agregation.Comment on le vérifie
Le nom du fichier évite d'emblée la collision de modules qui a coûté un renommage au #165 :
test_alertes.pyest pris par le collecteur,test_alertes_silver.pypar la zone argent, et pytest refuse deux modules homonymes tant que les répertoires de test n'ont pas d'__init__.py.Hors périmètre
Les alertes produites par nos propres règles (
source = 'regle'), qui relèvent du #39. La mise en cron, portée par la #159. L'affichage, porté par le #24. Le découpagemessage→titre/descriptionqu'attendAlerteOut, qui est une décision d'affichage.État : la chaîne est complète de bronze à
public.alerte, la demande #169 est ouverteBranche
marvin/168-alertes-zone-or, trois commits, empilée sur le #165 — à recibler surdevelopquand la #167 sera fusionnée.Les critères, un par un
gold/table=alerte/dt=…est écrite depuis la partition argent du même jour, une ligne par alerte.etl.gold.alertesprojette, il ne recalcule rien. Vérifié sur bronze réel : 2 984 alertes du 2026-09-06 traversent les trois zones sans perte ni doublon.public.alerteest chargée en upsert ; rejouer la journée ne crée pas de doublon. Sur(site_id, horodatage, type, source), la clé unique de la 0012 — et non suralerte_id, qui estgenerated always as identity: la base la produit, un insert qui la fournirait serait refusé. Les alertes partent dans la même transaction que la mesure et la qualité.Toutes les lignes portent
source = 'api_simulation'. Écrit en dur par la projection, jamais lu d'une colonne argent qui n'existe pas.taux_de_chargeest calculé depuis la capacité que la ligne argent porte déjà, sans jointure au référentiel.NULLet non zéro quand la capacité manque ou vaut zéro : un taux indéfini n'est pas un taux nul, et une division par zéro ferait échouer la journée entière pour une ligne de référentiel incomplète.Une valeur hors énumération fait échouer le job avant l'écriture. Doublon délibéré avec le contrôle de la zone argent, comme
agregation._controler_enumerationsle fait pour la mesure : une partition argent peut venir d'une version antérieure du job ou d'un rattrapage à la main.Les preuves
Chaîne des trois zones sur bronze réel, en local, sans rien écrire dans MinIO ni en base :
Ce que l'écriture a révélé, et qui dépasse le ticket
1. La table cible ne pouvait pas porter ce que l'écran demande.
public.alertea neuf colonnes,AlerteOuten attend dix, et quatre n'avaient aucune correspondance :titre,description,exigence,etat. Dans l'autre sens, la zone argent portealert_id,messageetbronze_keyqui n'avaient nulle part où aller — ce dernier étant notable, puisquepublic.mesureporte sa clé bronze pour l'ENF-07 depuis la 0010.D'où la migration
0017:libelle,etat,cle_bronze, plus un index partiel sur les seules alertes ouvertes.titre,descriptionetexigencerestent composés par l'API : ce sont des mises en forme, et la 0012 pose déjà la règle à propos du taux de charge.resolue_aattend ce qui résoudra les alertes, comme au #164.Ce n'est pas une surprise isolée : le #164 est le même ticket pour les recommandations. La zone or a été posée avant que les écrans ne soient contractualisés, et les deux tables d'événements ont le même trou.
2.
COPY … PARTITION_BY (dt)avec zéro ligne n'écrit aucun objet. Sans valeur dedtà partitionner, DuckDB ne crée pas de répertoire : une journée qui passerait de N alertes à zéro garderait sa partition or précédente. Théorique — une alerte ne disparaît de bronze qu'avec la rétention de 180 jours — mais réel, et la zone argent ne l'a pas : elle écrit à un chemin nommé. Écrit dans le module et gardé par un cas.3. Un piège à désamorcer plus tard.
etatest dans ledo updatede l'upsert, sans effet tant que la zone or ne porte que « ouverte ». Le jour où quelque chose résoudra les alertes, cette colonne devra en sortir — sinon un rejeu rouvrirait toutes les alertes fermées de la journée. Un cas de test porte la remarque à l'endroit où elle se lira.Ce qui reste, hors de ce lot
Rien ne tourne encore en cron : c'est la #159, ouverte et fusionnable. Tant qu'elle n'est pas passée, le seau
goldreste vide etpublic.alerteaussi — vérifié à l'instant, 0 objet.