runbook: backfill nyora-notes-tt 72h -- perte silencieuse 429 + faux 122 error_404
Documente les deux pieges de la fenetre de backfill mail (12-16/08) : 444 messages perdus en silence (18%) sur HTTP 429 embeddings jamais reessaye + max_tokens partage avec le raisonnement mimo-v2.5, corrige avec compteur d'echecs remonte au bilan (0 perte en tranche finale) ; et 122 error_404 qui mesuraient un resolveur de chemin perime (bugs corriges le 10/08) plutot que des dossiers reellement absents (105/122 recuperables). Regle generale versee pour les 3 instances. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
d8f8404bc7
commit
e7a53dc0b1
+87
@@ -0,0 +1,87 @@
|
||||
# Backfill mail nyora-notes-tt (72h) — perte silencieuse 429 + faux 122 error_404 (16/08/2026)
|
||||
|
||||
Fenêtre de backfill autonome sur `nyora-notes-tt` (5 tranches, 12→16/08/2026, supervision
|
||||
Telegram). Résultat : 643 → 4322 notes. Deux pièges rencontrés en cours de route valent d'être
|
||||
documentés séparément, parce que chacun aurait pu clôturer la fenêtre sur un état faussement
|
||||
propre.
|
||||
|
||||
## Piège 1 — un bilan « done » peut cacher 18% de messages perdus en silence
|
||||
|
||||
**Symptôme** : les tranches 1 et 2 annonçaient leurs dossiers `done` sans anomalie visible.
|
||||
Le comptage réel (lignes `WARNING ... ignore (extraction/embedding en echec)` dans le journal,
|
||||
jamais agrégées) a révélé **444 messages perdus sur 63 dossiers**, soit ~18% du volume traité.
|
||||
Invisible parce que : le dossier passe `done` malgré la perte, l'avertissement est noyé dans des
|
||||
milliers de lignes `INFO`, et **le bilan de fin de tranche ne comptait pas ces lignes**.
|
||||
|
||||
**Cause** : 66% des pertes = `HTTP 429 Too Many Requests` sur `/v1/embeddings` — le pipeline
|
||||
enchaîne un embedding par message sans temporisation ; le code traitait un 429 comme une erreur
|
||||
définitive et jetait le message. Le reste = `mimo-v2.5` (modèle à raisonnement) dont les
|
||||
`reasoning_tokens` s'imputent sur le même `max_tokens` que la réponse JSON attendue (2500) —
|
||||
un raisonnement long tronquait le JSON avant qu'il ne soit émis.
|
||||
|
||||
**Fix** (`pipeline_processor.py`, dépôt Gitea `bolbol/nyora-notes-tt` commit `838f28d`) :
|
||||
- `_appel_bifrost()` : réessais avec temporisation exponentielle (2s → 60s puis → 120s) sur
|
||||
429/5xx/erreur réseau, respect de l'en-tête `Retry-After`. Les 4xx hors 429 ne sont PAS
|
||||
réessayés (une requête malformée le reste). Validé sur la tranche 4 : 8 réessais déclenchés,
|
||||
jamais au-delà de la tentative 2/8 — **la profondeur suffit largement**, c'était son absence
|
||||
qui posait problème, pas le principe.
|
||||
- `max_tokens` 2500 → 8000 sur Mimo et DeepSeek + détection explicite de
|
||||
`finish_reason == "length"` (erreur nommée au lieu d'un JSON silencieusement tronqué).
|
||||
- Lecture du JSON dans les trois champs possibles (`content`, `reasoning`, `reasoning_content`) :
|
||||
la position du raisonnement variait selon la configuration du fournisseur.
|
||||
- **`messages_ignores` remonté dans le résultat de `process_folder` et dans le bilan de
|
||||
tranche**, avec le taux et la liste des dossiers touchés (`backfill_tranche.py`). C'est le
|
||||
changement qui compte le plus : sans lui, la perte reste invisible même si elle est corrigée
|
||||
ailleurs.
|
||||
|
||||
**Réparation** : les 63 dossiers amputés ont été repassés en `pending` — sans risque de doublon,
|
||||
la dédup de ce projet est par COMPTAGE (N messages du scan vs M notes en base, ingère la
|
||||
différence) et non par identification message à message. Résultat mesuré : `02 2024|⚖️ Cour des
|
||||
Comptes` a rendu exactement 40 notes nouvelles sur 69 messages vus, 29 déjà représentés — les 40
|
||||
qui manquaient. Taux de perte : ~18% (tranche 1-2, avant fix) → 2,9% (tranche 3, retries à 5/60s)
|
||||
→ **0% (tranche 4, retries à 8/120s)**.
|
||||
|
||||
**Règle générale** (versée côté PROTOCOL-INFRA des 3 instances, cf `[[hermes-instances-knowledge]]`) :
|
||||
tout pipeline qui appelle un LLM/embedding en boucle sur un lot doit exposer un compteur
|
||||
d'échecs/ignorés À CÔTÉ du compteur de succès dans son bilan de fin de lot — un statut `done`
|
||||
optimiste sur un lot n'est une preuve de rien tant que le delta réel (messages vus vs messages
|
||||
ingérés) n'est pas vérifié explicitement.
|
||||
|
||||
## Piège 2 — 122 dossiers "error_404" mesuraient un bug de résolution périmé, pas des dossiers absents
|
||||
|
||||
**Symptôme** : au reprise de la fenêtre, le checkpoint listait 122 dossiers en `error_404`. Une
|
||||
lecture rapide aurait pu conclure que 122 dossiers avaient disparu de la boîte et clôturer la
|
||||
fenêtre sur ~60 dossiers traitables au lieu de 145.
|
||||
|
||||
**Cause** : 121 de ces 122 `error_404` avaient été posés entre le 31/07 et le 02/08 —
|
||||
**avant** les correctifs bugs C et D du 10/08 côté `hermes-mail-browser`
|
||||
(`go_to_folder_path` : bug C, le 1er segment n'était cherché que sous la Boîte de réception ;
|
||||
bug D, un dossier AYANT DES ENFANTS ne pouvait pas être sélectionné — 63 dossiers du compte
|
||||
concernés). Les `error_404` mesuraient donc l'ancien résolveur, pas l'état réel de la boîte.
|
||||
|
||||
**Méthode de vérification** : confronter le checkpoint à un `/folders` frais, en normalisant
|
||||
casse + suffixe + préfixes emoji (les dossiers avaient été renommés `⏱️ Suivi`, `🤖 Veille`...
|
||||
entre-temps) plutôt que de comparer des chaînes brutes. Sur cette confrontation normalisée,
|
||||
105 des 122 `error_404` se sont révélés parfaitement résolubles. Signal d'alerte pendant le
|
||||
diagnostic : des dossiers `done` (donc traités avec succès) ressortaient classés « absents » —
|
||||
preuve que la comparaison était fautive, pas l'arbre.
|
||||
|
||||
**Fix appliqué** : 121 des 122 déclassés en `pending` après vérification individuelle contre
|
||||
l'arbre réel (script conservé sur le NAS : `nyora-notes-tt/backups/phase0_apply_resync.py`).
|
||||
Sur les 12 réellement introuvables, 12 se sont confirmés disparus (dossiers `Notification` type
|
||||
"Lot XX" devenus des feuilles sans enfant).
|
||||
|
||||
**Règle générale** : un statut d'échec (`error_404`, `error_409`...) porte une date implicite —
|
||||
celle du bug qui l'a produit. Après un correctif touchant la résolution/navigation, **ne jamais
|
||||
supposer qu'un lot d'échecs anciens reflète l'état actuel** sans le reconfronter à une lecture
|
||||
fraîche. Le coût de la vérification (un appel `/folders` + normalisation) est sans commune
|
||||
mesure avec le coût d'abandonner ~90 dossiers valides.
|
||||
|
||||
## Références
|
||||
|
||||
- Dépôt Gitea `bolbol/nyora-notes-tt`, commit `838f28d` (correctifs pipeline_processor.py,
|
||||
backfill_tranche.py, hermes_mail_client.py).
|
||||
- Snapshots de frontière : `nyora-notes-tt/backups/nyora-notes-tt.db.FINAL-backfill-20260816`
|
||||
et les snapshots intermédiaires `avant-correctif-mimo-20260814`, `fin-tranche3-20260816`,
|
||||
`fin-tranche4-20260816`.
|
||||
- Voir aussi [[hermes-mail-browser]], [[nyora-notes-tt-message-id-dedup-comptage-11-08-2026]].
|
||||
Reference in New Issue
Block a user