src/lib/cache.ts

function·app·1.4 KB · 52 lignes· Voir l'itinéraire
Annotation non disponible

Lance npm run annotate (nécessite ANTHROPIC_API_KEY dans .env.local) pour générer une annotation française par Claude Haiku 4.5.

2 exports

getOrSetCacheinvalidateCache

Code source· typescript

/**
 * Cache helper backed by Redis (ioredis).
 *
 * Usage :
 *   const data = await getOrSetCache(`story:${tenantId}`, 300, async () => {
 *     return computeStory(tenantId);
 *   });
 *
 * P0-3 fix : remplace les Map mémoire par-route (memory leak + inconsistance
 * multi-instance) par un cache distribué partagé entre tous les pods.
 *
 * Si Redis est down ou throw, on bypass le cache (le compute s'exécute quand
 * même). Pas de fail silencieux côté UX — au pire on perd l'optim, pas la
 * fonctionnalité.
 */
import { redis } from "@/lib/redis";

export async function getOrSetCache<T>(
  key: string,
  ttlSeconds: number,
  fn: () => Promise<T>,
): Promise<T> {
  try {
    const cached = await redis.get(key);
    if (cached !== null) {
      return JSON.parse(cached) as T;
    }
  } catch (err) {
    // Redis down / parse error → fallback compute
    console.warn(`[cache] redis GET failed for ${key}:`, err);
  }

  const value = await fn();

  try {
    await redis.set(key, JSON.stringify(value), "EX", ttlSeconds);
  } catch (err) {
    console.warn(`[cache] redis SET failed for ${key}:`, err);
  }

  return value;
}

/** Invalide une clé (utile pour pull-to-refresh ou post-mutation). */
export async function invalidateCache(key: string): Promise<void> {
  try {
    await redis.del(key);
  } catch (err) {
    console.warn(`[cache] redis DEL failed for ${key}:`, err);
  }
}