feat: persistance localStorage + stale-if-error serveur

Client — lib/localCache.ts (nouveau) :
  - saveCache / loadCache : wrapper localStorage préfixé "forex_v1_"
  - formatCacheDate : affiche l'âge du cache (< 1h, 2h, 3j…)

Client — CurrencyCard.tsx :
  - Sauvegarde chaque réponse macro réussie dans localStorage (clé macro_{currency})
  - Si l'API échoue → charge la dernière valeur connue depuis localStorage
  - Badge 🗄 "cache Xh" visible dans le header de la carte quand données stale

Client — page.tsx :
  - Même logique pour drivers, expectations, yields
  - Badge cache affiché dans le header à côté de l'heure
  - Footer : Bytez → Groq

Serveur — macro/route.ts :
  - stale-if-error : si tous les indicateurs reviennent null (panne API)
    et qu'un cache serveur précédent existe → le renvoie avec stale:true

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Capucine Gest
2026-05-28 22:58:27 +02:00
co-authored by Claude Sonnet 4.6
parent ecb815619b
commit 3c6e3bb52a
4 changed files with 146 additions and 16 deletions
+10
View File
@@ -178,7 +178,10 @@ export async function GET(req: NextRequest) {
if (!series) return NextResponse.json({ error: "Unknown currency" }, { status: 400 });
const cached = _cache.get(currency);
// Sert le cache pendant 24h sans re-fetcher
if (cached && Date.now() - cached.ts < 86_400_000) return NextResponse.json(cached.data);
// Garde une référence au cache précédent pour fallback stale-if-error
const staleCache = cached ?? null;
const key = process.env.FRED_API_KEY;
if (!key) return NextResponse.json({ error: "FRED_API_KEY missing" }, { status: 500 });
@@ -265,6 +268,13 @@ export async function GET(req: NextRequest) {
indicators.pmiMfg = toPmiIndicator(pmiMfgRaw);
indicators.pmiServices = toPmiIndicator(pmiSvcRaw);
// Stale-if-error : si tous les indicateurs sont null (API en panne),
// on renvoie le cache précédent plutôt que des tirets vides.
const hasAnyValue = Object.values(indicators).some((v) => v !== null);
if (!hasAnyValue && staleCache) {
return NextResponse.json({ ...staleCache.data, stale: true });
}
const data = { currency, indicators, fetchedAt: new Date().toISOString() };
_cache.set(currency, { data, ts: Date.now() });
return NextResponse.json(data);