@jamx-framework/cache
v1.0.0
Published
JAMX Framework — Cache with memory and Redis drivers
Maintainers
Readme
@jamx-framework/cache
Descripción
Módulo de caching para JAMX Framework. Proporciona una API unificada para almacenamiento en caché con múltiples backends (memoria, Redis, etc.), soportando TTL, invalidación por clave, y estrategias de caché como write-through y write-behind. Ideal para acelerar respuestas de APIs, bases de datos y cálculos costosos.
Cómo funciona
El módulo implementa un patrón de repositorio de caché con drivers intercambiables:
- Cache: Clase principal que maneja operaciones de get/set/delete con TTL
- Drivers: Implementaciones concretas (MemoryDriver, RedisDriver) que definen la persistencia
- Estrategias: Soporte para write-through (actualizar caché y origen simultáneamente) y write-behind (actualizar caché primero, origen después)
- Invalidación: Permite invalidar por clave, por patrón (prefix) o por completo
Componentes principales
- src/cache.ts: Clase
Cacheque gestiona operaciones de caché - src/drivers/memory.ts: Driver que almacena en memoria (Map)
- src/drivers/redis.ts: Driver que almacena en Redis
- src/drivers/types.ts: Tipos compartidos (
CacheDriver,CacheEntry, etc.) - src/index.ts: Punto de exportación
Uso básico
import { Cache, MemoryDriver } from '@jamx-framework/cache';
// Crear caché en memoria
const cache = new Cache(new MemoryDriver());
// Guardar con TTL de 5 minutos
await cache.set('users:123', { name: 'Juan', email: '[email protected]' }, 300);
// Obtener (con deserialización automática)
const user = await cache.get('users:123');
console.log('Usuario desde caché:', user);
// Verificar existencia
const exists = await cache.has('users:123');
console.log('¿Existe?', exists);
// Invalidar
await cache.delete('users:123');Con Redis
import { Cache, RedisDriver } from '@jamx-framework/cache';
const redisDriver = new RedisDriver({
host: 'localhost',
port: 6379,
password: 'secret',
});
const cache = new Cache(redisDriver);
await cache.set('session:abc123', { userId: 1 }, 3600);Ejemplos
Caché de consultas de base de datos
import { Cache, MemoryDriver } from '@jamx-framework/cache';
const cache = new Cache(new MemoryDriver());
async function findUser(id: string) {
const key = `user:${id}`;
// Intentar obtener desde caché
const cached = await cache.get(key);
if (cached) {
console.log('Hit caché');
return cached;
}
// Consultar base de datos
const user = await db.users.findById(id);
if (user) {
// Guardar en caché por 10 minutos
await cache.set(key, user, 600);
}
return user;
}Caché con invalidación por patrón
import { Cache, MemoryDriver } from '@jamx-framework/cache';
const cache = new Cache(new MemoryDriver());
// Guardar múltiples claves con prefijo común
await cache.set('products:1', product1, 300);
await cache.set('products:2', product2, 300);
await cache.set('products:3', product3, 300);
// Invalidar todas las claves que empiezan con 'products:'
await cache.invalidatePattern('products:*');
// Invalidar todo el caché
await cache.clear();Write-through pattern
import { Cache, MemoryDriver } from '@jamx-framework/cache';
const cache = new Cache(new MemoryDriver());
async function updateUser(id: string, data: Partial<User>) {
// 1. Actualizar caché primero
const existing = await cache.get(`user:${id}`) ?? null;
const updated = { ...existing, ...data };
await cache.set(`user:${id}`, updated, 600);
// 2. Actualizar base de datos
await db.users.update(id, data);
return updated;
}Caché de resultados de API
import { Cache, RedisDriver } from '@jamx-framework/cache';
const cache = new Cache(new RedisDriver({ url: 'redis://localhost:6379' }));
async function fetchExternalApi(endpoint: string, params: Record<string, string>) {
const query = new URLSearchParams(params).toString();
const key = `api:${endpoint}:${query}`;
// Intentar obtener desde caché
const cached = await cache.get(key);
if (cached) {
return cached as ApiResponse;
}
// Hacer request HTTP
const response = await fetch(`${endpoint}?${query}`);
const data = await response.json();
// Guardar en caché por 1 minuto
await cache.set(key, data, 60);
return data;
}Uso con inyección de dependencias
import { Container } from '@jamx-framework/core';
import { Cache, MemoryDriver } from '@jamx-framework/cache';
// Registrar en contenedor
Container.registerSingleton('cache', () => new Cache(new MemoryDriver()));
// Resolver y usar
const cache = Container.resolve<Cache>('cache');
await cache.set('config', { theme: 'dark' }, 3600);Flujo interno
- Inicialización: Se crea un
Cachecon un driver específico (Memory, Redis, etc.) - Operaciones:
get(),set(),has(),delete()se delegan al driver - TTL management: Cada entrada almacena
expiresAt;get()elimina entradas expiradas - Serialización: Los valores se serializan automáticamente (JSON.stringify/parse)
- Invalidación por patrón:
invalidatePattern()usakeys()+delete()para eliminar coincidencias - Estadísticas: El driver puede reportar hits/misses (opcional)
API Reference (Resumen)
Cache
constructor(driver: CacheDriver)async get<T>(key: string): Promise<T | null>async set<T>(key: string, value: T, ttl?: number): Promise<void>async has(key: string): Promise<boolean>async delete(key: string): Promise<void>async invalidatePattern(pattern: string): Promise<number>(número de claves eliminadas)async clear(): Promise<void>async keys(): Promise<string[]>
CacheDriver (interface)
async get<T>(key: string): Promise<CacheEntry<T> | null>async set<T>(key: string, value: T, ttl: number): Promise<void>async delete(key: string): Promise<void>async clear(): Promise<void>async keys(): Promise<string[]>
CacheEntry
value: TexpiresAt: number(timestamp en ms)createdAt: number
Performance Considerations
- MemoryDriver: Máxima velocidad, datos volátiles, ideal para development y small-scale
- RedisDriver: Persistencia, clustering, TTL nativo, ideal para production y distributed systems
- TTL granular: Cada clave puede tener su propio TTL
- Lazy expiration: Las entradas se eliminan al acceder (no hay background cleanup)
- Batch operations:
delete()ykeys()pueden ser costosos en Redis con muchas claves
Configuration Options
// MemoryDriver (sin configuración)
const memoryDriver = new MemoryDriver();
// RedisDriver
const redisDriver = new RedisDriver({
host: 'localhost',
port: 6379,
password: 'secret',
db: 0,
ttlSupport: true, // usar EXPIRE de Redis
prefix: 'jamx:', // prefijo para claves
});Testing
Tests en packages/cache/tests/unit/:
pnpm testCubre:
- Operaciones básicas (get/set/has/delete)
- TTL y expiración automática
- Invalidación por patrón
- Clear completo
- Drivers múltiples (memory, redis mock)
Compatibility
- Compatible con Node.js 18+
- Funciona en Windows, macOS, Linux
- RedisDriver requiere servidor Redis accesible
- No requiere dependencias globales
CLI Integration
jamx cache:clear: Limpia todo el cachéjamx cache:stats: Muestra estadísticas (hits, misses, tamaño)jamx cache:invalidate <pattern>: Invalida claves por patrón
This cache module provides a flexible, type-safe caching layer for JAMX applications, enabling developers to improve performance by reducing database load and accelerating response times with minimal code changes.
