Advanced

Comment concevoir et implementer des strategies de cache avec Claude Code

Apprenez a concevoir et implementer des strategies de cache avec Claude Code. Inclut des exemples de code pratiques et un guide etape par etape.

Avantages d’utiliser Claude Code pour concevoir des strategies de cache

Si le cache n’est pas correctement concu, il peut entrainer l’affichage de donnees obsoletes et le gaspillage de memoire. Claude Code peut analyser les patterns d’acces aux donnees de votre application et proposer puis implementer la strategie de cache optimale.

Implementation du cache avec Redis

> Implemente une couche de cache avec Redis.
> Avec invalidation de cache, gestion de TTL et pattern cache-aside.
// src/lib/cache.ts
import Redis from 'ioredis';

const redis = new Redis(process.env.REDIS_URL!);

interface CacheOptions {
  ttl?: number;      // en secondes
  prefix?: string;
}

export class CacheService {
  private defaultTTL = 300; // 5 minutes

  async get<T>(key: string, options?: CacheOptions): Promise<T | null> {
    const fullKey = this.buildKey(key, options?.prefix);
    const data = await redis.get(fullKey);
    if (!data) return null;

    try {
      return JSON.parse(data) as T;
    } catch {
      return null;
    }
  }

  async set<T>(key: string, value: T, options?: CacheOptions): Promise<void> {
    const fullKey = this.buildKey(key, options?.prefix);
    const ttl = options?.ttl ?? this.defaultTTL;

    await redis.setex(fullKey, ttl, JSON.stringify(value));
  }

  async getOrSet<T>(
    key: string,
    fetcher: () => Promise<T>,
    options?: CacheOptions
  ): Promise<T> {
    const cached = await this.get<T>(key, options);
    if (cached !== null) return cached;

    const data = await fetcher();
    await this.set(key, data, options);
    return data;
  }

  async invalidate(key: string, prefix?: string): Promise<void> {
    const fullKey = this.buildKey(key, prefix);
    await redis.del(fullKey);
  }

  async invalidatePattern(pattern: string): Promise<void> {
    const keys = await redis.keys(pattern);
    if (keys.length > 0) {
      await redis.del(...keys);
    }
  }

  private buildKey(key: string, prefix?: string): string {
    return prefix ? `${prefix}:${key}` : key;
  }
}

export const cache = new CacheService();

Implementation du pattern cache-aside

// src/services/product-service.ts
import { cache } from '@/lib/cache';
import { prisma } from '@/lib/db';

export class ProductService {
  async getProduct(id: string) {
    return cache.getOrSet(
      `product:${id}`,
      () => prisma.product.findUnique({
        where: { id },
        include: { category: true, reviews: { take: 10 } },
      }),
      { ttl: 600, prefix: 'products' }
    );
  }

  async getPopularProducts(limit = 20) {
    return cache.getOrSet(
      `popular:${limit}`,
      () => prisma.product.findMany({
        orderBy: { salesCount: 'desc' },
        take: limit,
        include: { category: true },
      }),
      { ttl: 300, prefix: 'products' }
    );
  }

  async updateProduct(id: string, data: UpdateProductInput) {
    const product = await prisma.product.update({
      where: { id },
      data,
    });

    // Invalider les caches lies
    await cache.invalidate(`product:${id}`, 'products');
    await cache.invalidatePattern('products:popular:*');

    return product;
  }
}

Configuration des headers de cache HTTP

// src/middleware.ts
import { NextResponse, NextRequest } from 'next/server';

export function middleware(req: NextRequest) {
  const res = NextResponse.next();
  const path = req.nextUrl.pathname;

  // Assets statiques : cache long terme
  if (path.match(/\.(js|css|png|jpg|svg|woff2)$/)) {
    res.headers.set('Cache-Control', 'public, max-age=31536000, immutable');
  }

  // API : pas de cache
  if (path.startsWith('/api/')) {
    res.headers.set('Cache-Control', 'no-store');
  }

  // Pages : cache court + ISR
  if (!path.startsWith('/api/') && !path.match(/\.[a-z]+$/)) {
    res.headers.set('Cache-Control', 'public, s-maxage=60, stale-while-revalidate=300');
  }

  return res;
}

Cache memoire (dans l’application)

Pour les donnees de petite taille, le cache en memoire est efficace.

// src/lib/memory-cache.ts
interface CacheEntry<T> {
  value: T;
  expiresAt: number;
}

export class MemoryCache {
  private store = new Map<string, CacheEntry<unknown>>();
  private maxSize: number;

  constructor(maxSize = 1000) {
    this.maxSize = maxSize;
  }

  get<T>(key: string): T | null {
    const entry = this.store.get(key);
    if (!entry) return null;

    if (Date.now() > entry.expiresAt) {
      this.store.delete(key);
      return null;
    }

    return entry.value as T;
  }

  set<T>(key: string, value: T, ttlMs: number): void {
    // Verification de la limite de taille
    if (this.store.size >= this.maxSize) {
      const firstKey = this.store.keys().next().value;
      if (firstKey) this.store.delete(firstKey);
    }

    this.store.set(key, {
      value,
      expiresAt: Date.now() + ttlMs,
    });
  }

  clear(): void {
    this.store.clear();
  }
}

// A utiliser pour les donnees frequemment accedees comme les configurations
export const configCache = new MemoryCache(100);

Guide de selection de strategie de cache

Type de donneesCache recommandeTTL estime
Configuration maitreMemoire + Redis1 heure
Profil utilisateurRedis10 minutes
Liste de produitsRedis + CDN5 minutes
Information de sessionRedis24 heures
Assets statiquesCDN1 an
Reponse APIHTTP Cache1 minute

Surveillance du cache

// Mesure du taux de succes du cache
export class CacheMetrics {
  private hits = 0;
  private misses = 0;

  recordHit() { this.hits++; }
  recordMiss() { this.misses++; }

  getHitRate(): number {
    const total = this.hits + this.misses;
    return total === 0 ? 0 : this.hits / total;
  }

  getStats() {
    return {
      hits: this.hits,
      misses: this.misses,
      hitRate: `${(this.getHitRate() * 100).toFixed(1)}%`,
    };
  }
}

Summary

Avec Claude Code, vous pouvez concevoir et implementer efficacement des strategies de cache multicouche incluant cache Redis, cache HTTP et cache memoire. Si vous documentez les politiques de conception de cache dans CLAUDE.md, vous obtiendrez une implementation coherente dans tout le projet. Pour la vue d’ensemble de l’amelioration des performances, consultez aussi les conseils pour tripler votre productivite.

Pour plus de details sur Claude Code, consultez la documentation officielle d’Anthropic. Pour plus de details sur Redis, consultez la documentation officielle de Redis.

#Claude Code #caching #Redis #performance #design