From 9ccbcc0619143bdab60090fe303657a9b2d6c50b Mon Sep 17 00:00:00 2001 From: Tallagrand Thierry Date: Mon, 14 Sep 2026 02:21:05 +0200 Subject: [PATCH] Une clef de session ecrite deux fois n est pas deux sessions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Airtria envoie la clef telle que PostgreSQL l affiche — 2026-09-12 11:55:54.493+02 — et la base me la rend en ISO. Meme instant, caracteres differents : mon Set les comptait deux fois, et le journal annoncait « 2 sessions, dont 1 ajoutee par le branchement » la ou le branchement n en contient qu une. L UPDATE resistait, les deux formes se transtypant en timestamptz. Ce qui ne resistait pas, c est le tableau sessions du detail, qui portait le doublon — et c est precisement lui que le controle de contradiction interroge sur les etiquettes suivantes. Trouve par le journal du service en essai a blanc, trois minutes avant la bascule du kill-switch. Mon harnais de verification ne pouvait pas le voir : il comptait les lignes SQL, pas les elements du Set. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj --- tools/historise-evcs.mjs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/historise-evcs.mjs b/tools/historise-evcs.mjs index 91e148c..9c98baa 100644 --- a/tools/historise-evcs.mjs +++ b/tools/historise-evcs.mjs @@ -1032,7 +1032,18 @@ async function appliquerEtiquetteConcierge(sql, client, st) { // evenement « on » a 15:55:15.485, soit 62 ms plus tard. Sans cette marge, // la session qui OUVRE un branchement est exclue de son propre groupe — ce // que le premier essai a blanc a effectivement montre (2 sessions sur 3). - const cibles = new Set(demandees); + // ⚠️ NORMALISER AVANT DE DEDUPLIQUER. Airtria envoie sa clef telle que + // PostgreSQL l'affiche — « 2026-09-12 11:55:54.493+02 » — et la base me la + // rend en ISO — « 2026-09-12T09:55:54.493Z ». Meme instant, caracteres + // differents : un Set les compte DEUX FOIS. L'UPDATE resistait (les deux se + // transtypent en timestamptz) mais le journal annoncait « 2 sessions, dont 1 + // ajoutee par le branchement » pour UNE seule session — et surtout le + // tableau `sessions` du detail portait le doublon, alors que c'est lui que + // le controle de contradiction interroge sur les etiquettes suivantes. + // Une clef illisible est gardee telle quelle : mieux vaut une clef brute + // qu'une clef inventee. + const enIso = (x) => { const d = new Date(x); return Number.isNaN(+d) ? String(x) : d.toISOString(); }; + const cibles = new Set(demandees.map(enIso)); let frontiereConnue = true; for (const d of demandees) { const { rows } = await lire( @@ -1053,7 +1064,7 @@ async function appliquerEtiquetteConcierge(sql, client, st) { // Aucune borne : le journal ne remonte pas assez loin. On n'invente pas // une frontiere qu'on n'a pas observee — on s'en tient a la liste recue. if (!rows.length) { frontiereConnue = false; continue; } - for (const r of rows) cibles.add(new Date(r.debut).toISOString()); + for (const r of rows) cibles.add(enIso(r.debut)); } // Deux etiquettes DIFFERENTES sur le meme cable : soit une frontiere fausse,