src/lib/cache.ts
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);
}
}
/**
* 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);
}
}