JSPM

@catalyst-team/cache

0.1.0
    • ESM via JSPM
    • ES Module Entrypoint
    • Export Map
    • Keywords
    • License
    • Repository URL
    • TypeScript Types
    • README
    • Created
    • Published
    • Downloads 253
    • Score
      100M100P100Q90740F

    Unified caching layer with Redis and in-memory support

    Package Exports

    • @catalyst-team/cache

    Readme

    @prediction-router/cache

    Three-layer cache package for Prediction Router V2.

    Architecture

    ┌─────────────────────────────────────────────────────────┐
    │                    Cache Layers                         │
    ├─────────────────────────────────────────────────────────┤
    │                                                         │
    │  L1: Memory (MemoryAdapter)                            │
    │  ├─ In-process Map with TTL                            │
    │  ├─ Fastest (< 1ms)                                    │
    │  ├─ Lost on restart                                     │
    │  └─ Not shared across instances                        │
    │                                                         │
    │  L2: Redis (RedisAdapter)                              │
    │  ├─ Persistent across restarts                         │
    │  ├─ Shared between instances                           │
    │  ├─ Auto-reconnection support                          │
    │  └─ Fast (1-5ms)                                       │
    │                                                         │
    │  L3: PostgreSQL (handled by application layer)         │
    │  └─ Long-term storage for historical data              │
    │                                                         │
    └─────────────────────────────────────────────────────────┘

    Data Flow

    Request → L1 (memory) → hit? → return
                         → miss ↓
             L2 (Redis)  → hit? → return + backfill L1
                         → miss ↓
             Source API  → fetch → update L1 + L2 → return

    Installation

    pnpm add @prediction-router/cache

    Usage

    Quick Start

    import { createCacheManager } from '@prediction-router/cache';
    
    // Create a cache manager with both L1 and L2
    const cache = createCacheManager({
      l1: { defaultTTL: 60 },        // 60 seconds
      l2: {                           // Redis config
        host: 'localhost',
        port: 6379,
        defaultTTL: 300,              // 5 minutes
      },
    });
    
    // Basic operations
    await cache.set('key', { data: 'value' }, { ttl: 60 });
    const value = await cache.get<{ data: string }>('key');
    await cache.del('key');
    
    // Cache-aside pattern
    const data = await cache.getOrSet('expensive-key', async () => {
      return await fetchExpensiveData();
    }, { ttl: 300 });

    Memory-Only Cache

    import { MemoryAdapter, CacheManager } from '@prediction-router/cache';
    
    const l1 = new MemoryAdapter({ defaultTTL: 60 });
    const cache = new CacheManager({ l1 });
    
    await cache.set('key', 'value');
    console.log(await cache.get('key')); // 'value'

    Redis-Only Cache

    import { RedisClient, RedisAdapter, CacheManager } from '@prediction-router/cache';
    
    const client = new RedisClient({
      host: process.env.REDIS_HOST || 'localhost',
      port: Number(process.env.REDIS_PORT) || 6379,
    });
    
    const l2 = new RedisAdapter(client.getClient(), { defaultTTL: 300 });
    const cache = new CacheManager({ l2 });
    
    await cache.set('key', { data: 'complex object' }, { ttl: 600 });

    Advanced Usage

    import { CacheManager, MemoryAdapter, RedisAdapter, RedisClient } from '@prediction-router/cache';
    
    // Create adapters
    const l1 = new MemoryAdapter({
      defaultTTL: 60,
      cleanupIntervalMs: 60000, // Clean up expired entries every minute
    });
    
    const redisClient = new RedisClient({
      host: 'localhost',
      port: 6379,
      password: process.env.REDIS_PASSWORD,
      db: 0,
      keyPrefix: 'app:', // All keys will be prefixed with 'app:'
    });
    
    const l2 = new RedisAdapter(redisClient.getClient(), {
      defaultTTL: 300,
    });
    
    // Create manager
    const cache = new CacheManager({ l1, l2 });
    
    // Skip L1 for shared data
    await cache.set('shared-data', { value: 123 }, {
      ttl: 600,
      skipL1: true, // Write directly to Redis, skip memory cache
    });
    
    // Get cache statistics
    const stats = cache.getStats();
    console.log(`Hit rate: ${(stats.hitRate * 100).toFixed(2)}%`);
    console.log(`L1 hits: ${stats.l1Hits}, L2 hits: ${stats.l2Hits}`);
    
    // Health check
    const health = await redisClient.healthCheck();
    if (health.healthy) {
      console.log(`Redis latency: ${health.latency}ms`);
    }

    API Reference

    CacheManager

    get<T>(key: string): Promise<T | null>

    Get a value from cache (L1 → L2 fallback).

    set<T>(key: string, value: T, options?: CacheSetOptions): Promise<void>

    Set a value in cache.

    Options:

    • ttl?: number - Time to live in seconds
    • skipL1?: boolean - Skip L1 and write directly to L2

    del(key: string): Promise<void>

    Delete a value from all cache layers.

    exists(key: string): Promise<boolean>

    Check if a key exists in any cache layer.

    getOrSet<T>(key: string, factory: () => Promise<T>, options?: CacheSetOptions): Promise<T>

    Get a value from cache, or fetch and cache it if not found.

    clear(): Promise<void>

    Clear all cache layers.

    getStats(): CacheStats

    Get cache statistics (hits, misses, hit rate).

    RedisClient

    healthCheck(): Promise<{ healthy: boolean; latency?: number; error?: string }>

    Perform a health check on Redis connection.

    getInfo(): { connected: boolean; status: string; reconnectAttempts: number }

    Get connection information.

    disconnect(): Promise<void>

    Gracefully disconnect from Redis.

    Environment Variables

    # Redis configuration
    REDIS_HOST=localhost
    REDIS_PORT=6379
    REDIS_PASSWORD=your-password
    REDIS_DB=0

    Testing

    # Unit tests (no Redis required)
    pnpm test
    
    # Integration tests (requires Redis)
    REDIS_HOST=localhost pnpm test:integration

    License

    MIT