fix: séparation du cache client et serveur pour résoudre l'erreur localStorage

This commit is contained in:
Julien Froidefond
2025-02-12 17:39:53 +01:00
parent b4d590e7e7
commit 1194bec24f
3 changed files with 130 additions and 16 deletions

View File

@@ -0,0 +1,121 @@
import { TTLConfig } from "@/types/cache";
class ClientCacheService {
private static instance: ClientCacheService;
private cache: Map<string, { data: unknown; expiry: number }> = new Map();
private static readonly DEFAULT_TTL = {
DEFAULT: 5 * 60,
HOME: 5 * 60,
LIBRARIES: 24 * 60 * 60,
SERIES: 5 * 60,
BOOKS: 5 * 60,
IMAGES: 24 * 60 * 60,
};
private constructor() {
// Private constructor to prevent external instantiation
}
public static getInstance(): ClientCacheService {
if (!ClientCacheService.instance) {
ClientCacheService.instance = new ClientCacheService();
}
return ClientCacheService.instance;
}
/**
* Retourne le TTL pour un type de données spécifique
*/
public getTTL(type: keyof typeof ClientCacheService.DEFAULT_TTL): number {
try {
const ttlConfig = localStorage.getItem("ttlConfig");
if (ttlConfig) {
const config = JSON.parse(ttlConfig) as TTLConfig;
const key = `${type.toLowerCase()}TTL` as keyof TTLConfig;
if (config[key]) {
// Convertir les minutes en secondes
return config[key] * 60;
}
}
} catch (error) {
console.error("Erreur lors de la lecture de la configuration TTL:", error);
}
return ClientCacheService.DEFAULT_TTL[type];
}
/**
* Met en cache des données avec une durée de vie
*/
set(key: string, data: any, type: keyof typeof ClientCacheService.DEFAULT_TTL = "DEFAULT"): void {
this.cache.set(key, {
data,
expiry: Date.now() + this.getTTL(type) * 1000,
});
}
/**
* Récupère des données du cache si elles sont valides
*/
get(key: string): any | null {
const cached = this.cache.get(key);
if (!cached) return null;
const now = Date.now();
if (cached.expiry > now) {
return cached.data;
}
this.cache.delete(key);
return null;
}
/**
* Supprime une entrée du cache
*/
delete(key: string): void {
this.cache.delete(key);
}
/**
* Vide le cache
*/
clear(): void {
this.cache.clear();
}
/**
* Récupère des données du cache ou exécute la fonction si nécessaire
*/
async getOrSet<T>(
key: string,
fetcher: () => Promise<T>,
type: keyof typeof ClientCacheService.DEFAULT_TTL = "DEFAULT"
): Promise<T> {
const now = Date.now();
const cached = this.cache.get(key);
if (cached && cached.expiry > now) {
console.log("Cache hit for key:", key);
return cached.data as T;
}
try {
const data = await fetcher();
this.cache.set(key, {
data,
expiry: now + this.getTTL(type) * 1000,
});
return data;
} catch (error) {
throw error;
}
}
invalidate(key: string): void {
this.cache.delete(key);
}
}
export const clientCacheService = ClientCacheService.getInstance();

View File

@@ -39,22 +39,7 @@ class ServerCacheService {
* Retourne le TTL pour un type de données spécifique * Retourne le TTL pour un type de données spécifique
*/ */
public getTTL(type: keyof typeof ServerCacheService.DEFAULT_TTL): number { public getTTL(type: keyof typeof ServerCacheService.DEFAULT_TTL): number {
// Essayer de récupérer la configuration utilisateur // Utiliser directement la valeur par défaut
try {
const ttlConfig = localStorage.getItem("ttlConfig");
if (ttlConfig) {
const config = JSON.parse(ttlConfig);
const key = `${type.toLowerCase()}TTL` as keyof typeof config;
if (config[key]) {
// Convertir les minutes en secondes
return config[key] * 60;
}
}
} catch (error) {
console.error("Erreur lors de la lecture de la configuration TTL:", error);
}
// Utiliser la valeur par défaut si pas de configuration utilisateur
return ServerCacheService.DEFAULT_TTL[type]; return ServerCacheService.DEFAULT_TTL[type];
} }

8
src/types/cache.ts Normal file
View File

@@ -0,0 +1,8 @@
export interface TTLConfig {
defaultTTL: number;
homeTTL: number;
librariesTTL: number;
seriesTTL: number;
booksTTL: number;
imagesTTL: number;
}