mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-22 22:48:15 +02:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
944d99733c | ||
|
|
8a27b310d2 | ||
|
|
6bb61cdbcc | ||
|
|
d384271a30 |
No files matched your search
@@ -121,11 +121,6 @@ export default function WeatherWidget() {
|
||||
const { data: weather, isLoading, error } = useQuery<WeatherResponse>({
|
||||
queryKey: ['/api/weather/current'],
|
||||
refetchInterval: 30 * 60 * 1000, // Refetch every 30 minutes
|
||||
// Données valables jusqu'au prochain rafraîchissement : pas de rechargement au remontage
|
||||
staleTime: 30 * 60 * 1000,
|
||||
// Pas de nouvel essai : un 404 (météo non configurée) ne changera pas, et le
|
||||
// serveur peut appeler l'API météo externe à chaque requête
|
||||
retry: false,
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
+57
-43
@@ -5421,58 +5421,59 @@ RÉSUMÉ DU SCAN
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
const previousYearDate = weatherService.getPreviousYearDate();
|
||||
|
||||
// Check if we already have today's data (deux lectures indépendantes)
|
||||
// Lectures du cache indépendantes : en parallèle
|
||||
let [currentYearData, previousYearData] = await Promise.all([
|
||||
storage.getWeatherData(today, true),
|
||||
storage.getWeatherData(previousYearDate, false),
|
||||
]);
|
||||
|
||||
// Les appels à l'API pour l'année en cours et l'année précédente sont
|
||||
// indépendants : ils sont lancés en parallèle
|
||||
await Promise.all([
|
||||
(async () => {
|
||||
// Fetch current year data if not in cache
|
||||
if (!currentYearData) {
|
||||
console.log("🌤️ [FETCH] Fetching current weather data from API");
|
||||
const apiData = await weatherService.fetchCurrentWeather(settings);
|
||||
if (apiData) {
|
||||
const weatherData = weatherService.convertApiDataToWeatherData(apiData, settings.location, true);
|
||||
if (weatherData) {
|
||||
try {
|
||||
currentYearData = await storage.createWeatherData(weatherData);
|
||||
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);
|
||||
}
|
||||
}
|
||||
// Les appels à l'API météo restent séquentiels : lancés en parallèle,
|
||||
// Visual Crossing peut refuser la seconde requête d'une même clé (limite
|
||||
// de requêtes simultanées) et la comparaison avec l'an dernier disparaît.
|
||||
|
||||
// Fetch current year data if not in cache
|
||||
if (!currentYearData) {
|
||||
console.log("🌤️ [FETCH] Fetching current weather data from API");
|
||||
const apiData = await weatherService.fetchCurrentWeather(settings);
|
||||
if (apiData) {
|
||||
const weatherData = weatherService.convertApiDataToWeatherData(apiData, settings.location, true);
|
||||
if (weatherData) {
|
||||
try {
|
||||
currentYearData = await storage.createWeatherData(weatherData);
|
||||
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 ; à défaut,
|
||||
// afficher quand même la réponse de l'API
|
||||
currentYearData = (await storage.getWeatherData(today, true)) ?? (weatherData as any);
|
||||
}
|
||||
}
|
||||
})(),
|
||||
(async () => {
|
||||
// Fetch previous year data if not in cache
|
||||
if (!previousYearData) {
|
||||
console.log("🌤️ [FETCH] Fetching previous year weather data from API");
|
||||
const apiData = await weatherService.fetchPreviousYearWeather(settings, previousYearDate);
|
||||
if (apiData) {
|
||||
const weatherData = weatherService.convertApiDataToWeatherData(apiData, settings.location, false);
|
||||
if (weatherData) {
|
||||
try {
|
||||
previousYearData = await storage.createWeatherData(weatherData);
|
||||
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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.warn("⚠️ [HISTORY] Could not fetch historical data - continuing with current year only");
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch previous year data if not in cache
|
||||
if (!previousYearData) {
|
||||
console.log("🌤️ [FETCH] Fetching previous year weather data from API");
|
||||
const apiData = await weatherService.fetchPreviousYearWeather(settings, previousYearDate);
|
||||
if (apiData) {
|
||||
const weatherData = weatherService.convertApiDataToWeatherData(apiData, settings.location, false);
|
||||
if (weatherData) {
|
||||
try {
|
||||
previousYearData = await storage.createWeatherData(weatherData);
|
||||
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 ; à 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");
|
||||
}
|
||||
}
|
||||
|
||||
// Repli : si l'API historique a échoué (quota épuisé, panne, plan sans
|
||||
// accès à l'historique), reprendre la ligne en cache la plus proche de
|
||||
@@ -5484,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 ? {
|
||||
|
||||
@@ -27,7 +27,8 @@ export class WeatherService {
|
||||
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
console.error(`Weather API error: ${response.status} ${response.statusText}`);
|
||||
const reason = (await response.text().catch(() => '')).slice(0, 300);
|
||||
console.error(`Weather API error: ${response.status} ${response.statusText} ${reason}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -51,7 +52,9 @@ export class WeatherService {
|
||||
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
console.error(`🌤️ [ERROR] Weather API error for previous year: ${response.status} ${response.statusText}`);
|
||||
// Visual Crossing explique le refus dans le corps (quota, plan, clé...)
|
||||
const reason = (await response.text().catch(() => '')).slice(0, 300);
|
||||
console.error(`🌤️ [ERROR] Weather API error for previous year: ${response.status} ${response.statusText} ${reason}`);
|
||||
|
||||
// Pour les données historiques, certains comptes peuvent ne pas avoir accès
|
||||
if (response.status === 401) {
|
||||
|
||||
Reference in new issue
Block a user