Mise en production : le tableau de bord quitte les fixtures #198
No reviewers
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
g2/enervision!198
Loading…
Reference in a new issue
No description provided.
Delete branch "develop"
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?
Mise en production. Quatorze commits de retard sur
main.Ce que ça change en prod
enervision_prod. C'est le point le plus visible,derniere_releveaffichait le 1er septembre.nullquand la veille est absente au lieu d'un pourcentage inventé.reprise.md,deploiement.md) ont une section panne et une section retour arrière, et le filet durestoren'écrase plus la sauvegarde qu'il protège.--jours-test.Vérifications
Chaîne verte sur chaque demande fusionnée. 1 068 tests unitaires,
ruff,mypy --strict. Les trois requêtes SQL du tableau de bord ont été passées à la main surenervision_prod.Après le déploiement
Rien à jouer manuellement. Le déploiement recrée
apietsupervision.repository.py ne lit plus fixtures.py DU TOUT. Il en portait trente et un renvois hier matin, dix ce midi, zéro maintenant. Ce qui devient réel, et la mesure côté production : consommation_kw 176,220 kW au lieu de 104,0 figé derniere_releve 10h59 aujourd'hui au lieu du 1er septembre 16h42 disponibilite_pct 80,6 % lu dans qualite_jour imputation_pct dérivé de repartition_methode, la colonne n'existe pas taux_de_charge, palier deviennent vrais d'eux-mêmes, ce sont des dérivés consommation_veille 3 619,3 kW, le même seau horaire à J-1 recommandations 2 actives sur SITE003, produites par R1 Le champ le plus visible était derniere_releve : l'écran affichait le 1er septembre pendant que la relève tournait à la minute et que la base portait 88 440 lignes pour le seul SITE001. Sur un tableau de bord, la première chose qu'on regarde est l'heure. DEUX CHAMPS DEVIENNENT FACULTATIFS, de bout en bout. derniere_releve un site jamais mesuré n'en a pas. Lui en inventer une serait pire que de ne rien afficher, et le masquer donnerait un parc plus petit que le parc. Le front rend un tiret : formaterHeure(null) valait 01:00, une heure plausible et fausse. consommation_veille le seau de la veille peut manquer. ecart_veille_pct rend alors None, et aussi quand la veille vaut zéro : un parc à l'arrêt ne donne pas un écart infini, il ne donne pas d'écart du tout. DISPONIBILITE_CIBLE_PCT reste une constante, et sort de fixtures.py. Ce n'est pas une donnée, c'est un objectif d'équipe qu'aucune table ne porte : c'était son voisinage avec des valeurs inventées qui la rendait suspecte. Trois doubles de test corrigés, et chacun cachait un défaut : FakeCurseur rendait ses lignes QUELLE QUE SOIT la requête. Il rendait donc les prévisions à qui demandait le référentiel. les réponses ignoraient les paramètres : le double rendait les recommandations de tout le parc à qui demandait celles d'un seul site, et le cas d'un site sans recommandation passait au vert sur un dépôt qui n'aurait rien filtré. CurseurDouble exigeait son second argument alors que psycopg le rend facultatif. Le double était plus strict que ce qu'il double. Les fixtures restent, à leur place : le jeu d'essai. Les sept sites, le site muet et les quatre paliers sont inchangés pour les cas, et c'est le point, aucun d'eux n'a eu à bouger. Les trois requêtes sont éprouvées contre enervision_prod avant d'être écrites. 1 068 tests, ruff propre, mypy --strict propre sur 23 fichiers.Relu en entier. Approuvé, avec UNE CONDITION : la #200 doit entrer dans
developavant que celle-ci parte surmain. Elle corrige le seul point bloquant que la relecture a trouvé, elle est verte, et sans elle la mise en production emporte le défaut décrit plus bas.Le point bloquant, et ce que la #200 change
_consommation_veille_kwrestreint bien la somme d'hier aux sites mesurés aujourd'hui — c'est l'apport du #179, ettest_la_veille_est_sommee_sur_les_seuls_sites_mesuresle garde. Mais rien ne vérifiait que la veille les portait TOUS.mesure_horaire.moyenne_kwvautavg(valeur_kw) filter (where indicateur_qualite <> 'critical')(0016) : un site dont le seau de la veille est vide ou entièrement dégradé rendnull,sum()l'ignore en silence, et six sites d'aujourd'hui se comparaient à trois d'hier. C'est le faux delta que le périmètre corrigeait, retourné — une perte de COUVERTURE affichée comme une baisse de CONSOMMATION. Le 08/09 à 08 h, la source marquait 416 relevés sur 420 encritical(#112) : le cas n'a rien de théorique, et il tombe sur le premier chiffre de l'écran.Signe que le garde-fou était prévu mais pas câblé :
count(*) as sitesétait sélectionné et jamais lu. La #200 le lit, encount(moyenne_kw)— une ligne présente dont la moyenne est nulle n'est pas une couverture — et rendNonesur une veille partielle. Le contrat le permettait déjà :consommation_veille_kwetecart_veille_pctsont nullables depuis cette demande-ci, etSyntheseParc.vueles garde derrière unv-if. Au passage, le double de la veille répondait « sites: 7 » à une requête qui en demandait six : il décrivait une base impossible, il suit maintenant ses paramètres, et un cas rescripte une veille à trois sites.Le reste de la relecture
La nullabilité de
derniere_releve,consommation_veille_kwetecart_veille_pctest propagée partout :SiteOut,SyntheseParcOut, lev-ifde la synthèse, etformaterHeurequi rend « — » là oùnew Date(null)donnait l'epoch, soit01:00— une heure plausible pour un site jamais mesuré. Aucun autre lecteur de ces trois champs dans l'API.Toutes les colonnes des nouvelles requêtes existent :
site(0007),qualite_jour(0013),recommandation(0014 et 0019).horodatageesttimestamptz, donc le front reçoit un décalage explicite et n'interprète pas une heure UTC comme locale.statut = 'active'est cohérent avec l'index unique partiel de la 0019.Côté sauvegarde,
PG_BACKUP_DESTisole vraiment le filet :.dernier-etatsuit$DEST, et la rétention est en-maxdepth 1, donc le sous-répertoire n'est pas purgé.publier_metriquesort en 0 quand le répertoire est absent, donc lePG_BACKUP_TEXTFILE_DIR: /nonexistentderestore.ymlfait ce qu'il annonce et le filet ne repose plus la métrique de réussite. Lefind *.dumpdu rôle backup ferme bien le trou du.dernier-etatcaché.Deux réserves, pas bloquantes, à garder en tête
L'écart compare un instantané (la dernière relève par site) à une moyenne horaire. Le corriger demanderait de lire aussi le seau du jour dans
mesure_horaire, qui exclut l'heure en cours (end_offset => 1 hour) : le chiffre de tête aurait jusqu'à deux heures de retard. C'est un moins bon compromis la veille du jury, donc rien ne bouge, mais l'asymétrie est réelle.Et
qualite_jourest lue parorder by jour desc limit 1, sans borne : si le job de qualité s'arrête, l'écran continue d'afficher la disponibilité du dernier jour calculé sans dire qu'elle est vieille. À traiter avec la fraîcheur du reste, pas ici.