3 Commits
Author SHA1 Message Date
Claude 944d99733c fix(meteo): afficher la réponse de l'API même si son enregistrement échoue
La température de l'an dernier disparaissait alors que Visual Crossing
répondait correctement (tableau de bord : requêtes réussies, 0 échec,
et l'URL d'historique testée dans le navigateur renvoie bien la journée).
Quand l'enregistrement de la réponse en cache échouait (par exemple une
contrainte d'unicité sur la date déjà occupée par la météo relevée ce
jour-là l'an dernier), la route relisait le cache, n'y trouvait rien et
jetait la donnée reçue : previousYear restait à null et l'API était
réinterrogée à chaque affichage.

La route garde désormais la réponse de l'API pour l'affichage quand
l'enregistrement échoue (année en cours et année précédente), et
journalise une réponse d'historique vide. Reproduit sur un Postgres local
avec une contrainte UNIQUE (date, location) et une API simulée renvoyant
la réponse réelle : N-1 vide avant, 14,1° après ; sans contrainte, le
comportement est inchangé.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MsDJjQrAggcJwbbBtKhgyb
2026-10-05 14:22:44 +00:00
Claude 8a27b310d2 fix(meteo): repli sur la météo relevée l'an dernier pour la comparaison N-1
La comparaison avec l'année dernière disparaît quand Visual Crossing
refuse durablement l'historique (plan, quota) : le repli précédent ne
cherchait que des lignes N-1 déjà en cache (is_current_year = false) à
7 jours près, qui n'existent plus si l'historique échoue depuis plus
d'une semaine.

La table weather_data garde pourtant la météo relevée chaque jour l'an
dernier, quand ces dates étaient « aujourd'hui » (is_current_year =
true). La route l'utilise désormais en second repli, au jour le plus
proche de la date cible (7 jours max), et journalise l'absence totale de
donnée N-1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MsDJjQrAggcJwbbBtKhgyb
2026-10-05 14:10:06 +00:00
Claude 6bb61cdbcc fix(db): ne plus arrêter le serveur quand Postgres coupe une connexion
Quand la base redémarre (redéploiement, restart du conteneur) ou que le
réseau coupe, pg-pool émet 'error' pour chaque connexion inactive
interrompue. Aucun écouteur n'était branché sur le pool de server/db.ts :
Node levait l'événement non géré et arrêtait tout le serveur, avec un
dump géant du client pg dans les logs. Le pool écarte déjà la connexion
fautive et en ouvre une neuve à la requête suivante : on se contente de
journaliser le code et le message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MsDJjQrAggcJwbbBtKhgyb
2026-10-05 14:07:23 +00:00
2 changed files with 29 additions and 4 deletions

No files matched your search

+8
View File
@@ -30,6 +30,14 @@ if (isProduction && dbUrl && (dbUrl.includes('logiflow-db') || dbUrl.includes('l
db = drizzle({ client: pool, schema });
// Une connexion inactive coupée par Postgres (redémarrage ou redéploiement de
// la base, coupure réseau) fait émettre 'error' au pool. Sans écouteur, Node
// arrête tout le serveur ; le pool écarte déjà la connexion fautive et en
// ouvre une neuve à la requête suivante, il suffit donc de journaliser.
pool.on('error', (err: any) => {
console.error('❌ PostgreSQL idle connection error (connexion écartée):', err?.code || '', err?.message);
});
// Test connection
try {
await pool.connect().then((client: any) => {
+21 -4
View File
@@ -5443,8 +5443,9 @@ RÉSUMÉ DU SCAN
console.log("✅ [CACHE] Current year data saved to cache");
} catch (error: any) {
console.warn("⚠️ [CACHE] Could not save current year data (may already exist):", error.message);
// Récupérer les données existantes au lieu de créer
currentYearData = await storage.getWeatherData(today, true);
// Récupérer les données existantes au lieu de créer ; à défaut,
// afficher quand même la réponse de l'API
currentYearData = (await storage.getWeatherData(today, true)) ?? (weatherData as any);
}
}
}
@@ -5462,9 +5463,12 @@ RÉSUMÉ DU SCAN
console.log("✅ [CACHE] Previous year data saved to cache");
} catch (error: any) {
console.warn("⚠️ [CACHE] Could not save previous year data (may already exist):", error.message);
// Récupérer les données existantes au lieu de créer
previousYearData = await storage.getWeatherData(previousYearDate, false);
// Récupérer les données existantes au lieu de créer ; à défaut,
// afficher quand même la réponse de l'API plutôt que de la perdre
previousYearData = (await storage.getWeatherData(previousYearDate, false)) ?? (weatherData as any);
}
} else {
console.warn(`⚠️ [HISTORY] Empty historical response for ${previousYearDate}`);
}
} else {
console.warn("⚠️ [HISTORY] Could not fetch historical data - continuing with current year only");
@@ -5481,6 +5485,19 @@ RÉSUMÉ DU SCAN
}
}
// Second repli : la météo relevée l'an dernier, au jour le jour, quand ces
// dates étaient « aujourd'hui » (lignes is_current_year = true datées de
// l'année précédente). Elle reste disponible même si l'API refuse
// durablement l'historique (plan, quota).
if (!previousYearData) {
previousYearData = await storage.getNearestWeatherData(previousYearDate, true, 7);
if (previousYearData) {
console.log(`🌤️ [FALLBACK] Using weather recorded last year (${previousYearData.date}) for target ${previousYearDate}`);
} else {
console.warn(`⚠️ [FALLBACK] No previous-year weather available around ${previousYearDate}`);
}
}
// Toujours retourner une réponse même si seule l'année actuelle est disponible
const response = {
currentYear: currentYearData ? {