[135] La grille de la journée en cours s'arrête aux minutes écoulées #142

Merged
lenaic merged 2 commits from lenaic/135-grille-journee-en-cours into develop 2026-09-04 08:44:12 +00:00
Owner

Ferme #135.

Le défaut

grille_du_jour() rendait range(MINUTES_PAR_JOUR), soit 1440 minutes quelle que
soit l'heure. Ce nombre devient minutes_attendues, dénominateur de
taux_de_trous, que le garde-fou du §11 refuse au delà de 30 %.

Les minutes pas encore arrivées comptaient donc comme manquantes. Ce matin à
7 h 18 UTC :

ERROR etl.silver journée refusée, rien n'a été écrit :
  taux de trous anormal (> 30%) : SITE001 70.1% ...

alors que la collecte est intacte : 439 objets bronze par site pour 438
minutes écoulées depuis minuit, 1024 passes du collecteur, toutes à 7 sites sur
7, zéro erreur.

Le lanceur est prévu pour tourner toutes les heures sur la journée courante. Le
job ne pouvait donc jamais réussir avant 17 h UTC, et le seau silver est
resté à zéro objet depuis le déploiement du #34.

Ce que fait la correction

minutes_attendues(jour, instant) rend 1440 pour une journée révolue et les
seules minutes écoulées pour la journée en cours. La minute en cours est exclue,
le collecteur relevant à la minute.

La normalisation passe par a_la_minute, pas par un astimezone direct. Un
horodatage naïf y serait présumé local : deux heures de grille de trop sur un
serveur en UTC+2, et le défaut rouvert sur les deux premières heures de chaque
journée.

disponibilite_jour gagne une colonne journee_complete. Sans elle une ligne à
32 % de disponibilité se lit comme une journée catastrophique alors qu'elle est
simplement en cours, et un entraînement la prendrait pour une journée finie.

Le trou trouvé en me relisant

La passe de 23 h écrit jusqu'à 22 h 59, et celle de minuit porte déjà sur le jour
suivant : la dernière heure de chaque journée n'aurait jamais été écrite.

Le second commit corrige ça. À minuit la passe ferme la veille, seul moment où la
journée d'avant est complète. Un --jour explicite n'est jamais réinterprété.

Éprouvé

Quinze cas ajoutés. Onze virent au rouge quand on réintroduit le défaut dans
grille.py, vérifié dans les deux sens. Les autres couvrent ce que la correction
ne doit pas casser :

  • le garde-fou reste armé en milieu de journée, une collecte muette depuis 1 h 40 est toujours refusée ;
  • l'idempotence tient, une passe plus tardive réécrit la même partition en plus long, silver_run_id et processed_at mis à part ;
  • une journée révolue garde ses 1440 minutes.

Les contextes de test dataient la passe du jour même, ce qui donnait des grilles
partielles partout. Ils passent au lendemain, situation d'un rejeu.

178 passed, ruff et mypy propres.

Vérification en production, sans rien polluer

La passe manuelle de ce matin, seuil desserré et écriture détournée vers un seau
silver-essai, a produit 10 080 lignes sur 7 sites, trois tables Parquet,
imputation comprise. Le seau silver de production est resté à 0 objet.

Ce que cette demande ne fait pas

Elle ne planifie rien : le job n'est appelé par aucune crontab, et deux obstacles
empêchent d'en poser une. C'est le #136, à fusionner après celle-ci.

Ferme #135. ## Le défaut `grille_du_jour()` rendait `range(MINUTES_PAR_JOUR)`, soit 1440 minutes quelle que soit l'heure. Ce nombre devient `minutes_attendues`, dénominateur de `taux_de_trous`, que le garde-fou du §11 refuse au delà de 30 %. Les minutes pas encore arrivées comptaient donc comme manquantes. Ce matin à 7 h 18 UTC : ``` ERROR etl.silver journée refusée, rien n'a été écrit : taux de trous anormal (> 30%) : SITE001 70.1% ... ``` alors que la collecte est **intacte** : 439 objets bronze par site pour 438 minutes écoulées depuis minuit, 1024 passes du collecteur, toutes à 7 sites sur 7, zéro erreur. Le lanceur est prévu pour tourner toutes les heures sur la journée courante. Le job ne pouvait donc **jamais** réussir avant 17 h UTC, et le seau `silver` est resté à zéro objet depuis le déploiement du #34. ## Ce que fait la correction `minutes_attendues(jour, instant)` rend 1440 pour une journée révolue et les seules minutes écoulées pour la journée en cours. La minute en cours est exclue, le collecteur relevant à la minute. **La normalisation passe par `a_la_minute`, pas par un `astimezone` direct.** Un horodatage naïf y serait présumé local : deux heures de grille de trop sur un serveur en UTC+2, et le défaut rouvert sur les deux premières heures de chaque journée. `disponibilite_jour` gagne une colonne `journee_complete`. Sans elle une ligne à 32 % de disponibilité se lit comme une journée catastrophique alors qu'elle est simplement en cours, et un entraînement la prendrait pour une journée finie. ## Le trou trouvé en me relisant La passe de 23 h écrit jusqu'à 22 h 59, et celle de minuit porte déjà sur le jour suivant : **la dernière heure de chaque journée n'aurait jamais été écrite.** Le second commit corrige ça. À minuit la passe ferme la veille, seul moment où la journée d'avant est complète. Un `--jour` explicite n'est jamais réinterprété. ## Éprouvé Quinze cas ajoutés. **Onze virent au rouge** quand on réintroduit le défaut dans `grille.py`, vérifié dans les deux sens. Les autres couvrent ce que la correction ne doit pas casser : - le garde-fou reste armé en milieu de journée, une collecte muette depuis 1 h 40 est toujours refusée ; - l'idempotence tient, une passe plus tardive réécrit la même partition en plus long, `silver_run_id` et `processed_at` mis à part ; - une journée révolue garde ses 1440 minutes. Les contextes de test dataient la passe du jour même, ce qui donnait des grilles partielles partout. Ils passent au lendemain, situation d'un rejeu. `178 passed`, `ruff` et `mypy` propres. ## Vérification en production, sans rien polluer La passe manuelle de ce matin, seuil desserré et écriture détournée vers un seau `silver-essai`, a produit **10 080 lignes sur 7 sites**, trois tables Parquet, imputation comprise. Le seau `silver` de production est resté à 0 objet. ## Ce que cette demande ne fait pas Elle ne planifie rien : le job n'est appelé par aucune crontab, et deux obstacles empêchent d'en poser une. C'est le #136, à fusionner après celle-ci.
lenaic self-assigned this 2026-09-04 08:08:22 +00:00
Le garde-fou de sortie compare le nombre de trous à `minutes_attendues`, que
`grille_du_jour` fixait à 1440 quelle que soit l'heure. Les minutes pas encore
arrivées comptaient donc comme manquantes : à 7 h du matin le job annonçait
70,1 % de trous sur une collecte pourtant intacte, et refusait d'écrire.

Le lanceur est prévu pour tourner toutes les heures sur la journée courante.
Les deux règles étaient incompatibles : le job ne pouvait jamais réussir avant
17 h UTC, quel que soit l'état des données. La zone argent est restée à zéro
objet depuis le déploiement du #34.

`minutes_attendues(jour, instant)` rend 1440 pour une journée révolue et les
seules minutes écoulées pour la journée en cours. La minute en cours est exclue,
le collecteur relevant à la minute. La normalisation passe par `a_la_minute` et
non par un `astimezone` direct, qui présumerait l'heure locale et rendrait deux
heures de grille de trop sur un serveur en UTC+2.

À minuit pile, aucune minute n'est révolue : la passe sort sans écrire plutôt
que de poser trois tables vides, qui effaceraient le rejeu de la veille. La
tâche planifiée passera par ce cas chaque nuit.

`disponibilite_jour` gagne une colonne `journee_complete`. Sans elle, une ligne
à 32 % de disponibilité se lit comme une journée catastrophique alors qu'elle
est simplement en cours, et un entraînement la prendrait pour une journée finie.

Les contextes de test dataient la passe du jour même, ce qui donnait des grilles
partielles partout. Ils passent au lendemain, situation d'un rejeu, la seule où
la journée compte ses 1440 minutes.

Onze cas ajoutés, dont dix virent au rouge sur le défaut réintroduit. Le
onzième vérifie que borner la grille ne désarme pas le garde-fou.

Ferme #135
etl: la passe de minuit ferme la veille au lieu d'ouvrir le jour
Some checks failed
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 2m8s
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 4s
Intégration / Aucun secret commité (pull_request) Successful in 2s
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Failing after 7m15s
9d80715ab7
Trou trouvé en relisant le correctif précédent. La tâche est prévue toutes les
heures sur la journée courante, et la grille s'arrête aux minutes révolues : la
passe de 23 h écrit donc jusqu'à 22 h 59, et celle de minuit porte déjà sur le
jour suivant. La dernière heure de chaque journée n'aurait jamais été écrite.

Minuit est le seul moment où la journée d'avant est complète : c'est là qu'on la
clôt. La règle ne vaut que pour une passe sans `--jour`. Un jour nommé
explicitement n'est jamais réinterprété, le rejeu manuel devant traiter la
journée qu'on lui donne.

La sortie sans écriture reste, pour le cas d'un `--jour` sur le jour même à
minuit, et reste éprouvée.

Quatre cas ajoutés sur le choix de la journée, dont celui d'une horloge en
UTC+2 : 00 h 30 à Paris fait 22 h 30 la veille en UTC, et sans la conversion la
passe traiterait le mauvais jour deux heures par nuit.
justine approved these changes 2026-09-04 08:14:42 +00:00
lenaic merged commit 14b12735e2 into develop 2026-09-04 08:44:12 +00:00
lenaic deleted branch lenaic/135-grille-journee-en-cours 2026-09-04 08:44:12 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
g2/enervision!142
No description provided.