Files
michaelschiemer/docs/modules/cache-manager.md
Michael Schiemer 36ef2a1e2c
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
fix: Gitea Traefik routing and connection pool optimization
- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
2025-11-09 14:46:15 +01:00

8.3 KiB

Cache Manager Module

Intelligent Caching for API Responses and Computed Values

The Cache Manager Module provides a comprehensive caching system with multiple storage backends and caching strategies.


Features

  • Memory Cache - Fast in-memory caching
  • IndexedDB Cache - Persistent browser storage
  • Cache Strategies - Multiple caching strategies (cache-first, network-first, stale-while-revalidate, etc.)
  • Cache Invalidation - Pattern-based cache invalidation
  • Cache Warming - Preload cache values
  • Cache Analytics - Track cache performance
  • Integration with RequestDeduplicator - Works with LiveComponent request deduplication

Quick Start

Basic Usage

import { CacheManager, CacheStrategy } from './modules/cache-manager/index.js';

// Create cache manager
const cache = CacheManager.create({
    defaultStrategy: CacheStrategy.STALE_WHILE_REVALIDATE,
    defaultTTL: 3600000 // 1 hour
});

// Get or set value
const data = await cache.getOrSet('users', async () => {
    const response = await fetch('/api/users');
    return await response.json();
});

// Get from cache
const cached = await cache.get('users');

// Set in cache
await cache.set('users', data, { ttl: 1800000 }); // 30 minutes

Module System Integration

<!-- Enable global cache manager -->
<script type="module">
    import { init } from './modules/cache-manager/index.js';
    
    init({
        defaultStrategy: 'stale-while-revalidate',
        enableIndexedDB: true
    });
</script>

<!-- Access globally -->
<script>
    // Get or set
    const data = await window.CacheManager.getOrSet('key', async () => {
        return await fetch('/api/data').then(r => r.json());
    });
</script>

API Reference

CacheManager.create(config)

Create a new CacheManager instance.

Parameters:

  • config.defaultStrategy - Default caching strategy
  • config.defaultTTL - Default time-to-live in milliseconds
  • config.maxMemorySize - Maximum items in memory cache
  • config.enableIndexedDB - Enable IndexedDB persistence
  • config.indexedDBName - IndexedDB database name
  • config.enableAnalytics - Enable cache analytics

Example:

const cache = CacheManager.create({
    defaultStrategy: CacheStrategy.STALE_WHILE_REVALIDATE,
    defaultTTL: 3600000,
    maxMemorySize: 100,
    enableIndexedDB: true
});

cache.get(key, options)

Get value from cache.

Parameters:

  • key - Cache key
  • options.strategy - Caching strategy override
  • options.ttl - Time-to-live override

Returns: Promise<any | null>

cache.set(key, value, options)

Set value in cache.

Parameters:

  • key - Cache key
  • value - Value to cache
  • options.strategy - Caching strategy
  • options.ttl - Time-to-live

Returns: Promise<void>

cache.getOrSet(key, computeFn, options)

Get value from cache or compute and cache it.

Parameters:

  • key - Cache key
  • computeFn - Function to compute value if not cached
  • options - Cache options

Returns: Promise<any>

Example:

const users = await cache.getOrSet('users', async () => {
    const response = await fetch('/api/users');
    return await response.json();
}, { ttl: 1800000 });

cache.delete(key)

Delete value from cache.

Parameters:

  • key - Cache key

Returns: Promise<void>

cache.clear()

Clear all cache.

Returns: Promise<void>

cache.invalidate(pattern)

Invalidate cache entries matching a pattern.

Parameters:

  • pattern - String, RegExp, or function

Returns: Promise<void>

Example:

// Invalidate all user-related cache
await cache.invalidate('user:');

// Invalidate with regex
await cache.invalidate(/^user:\d+$/);

// Invalidate with function
await cache.invalidate(key => key.startsWith('user:'));

cache.warm(keys, computeFn)

Warm cache by preloading values.

Parameters:

  • keys - Array of cache keys
  • computeFn - Function to compute value for each key

Returns: Promise<void>

Example:

await cache.warm(['user:1', 'user:2', 'user:3'], async (key) => {
    const userId = key.split(':')[1];
    const response = await fetch(`/api/users/${userId}`);
    return await response.json();
});

cache.getAnalytics()

Get cache performance analytics.

Returns: CacheAnalytics

Example:

const analytics = cache.getAnalytics();
console.log(`Hit rate: ${analytics.hitRate}%`);
console.log(`Hits: ${analytics.hits}, Misses: ${analytics.misses}`);

Cache Strategies

Cache-First

Use cache if available, otherwise fetch.

const data = await cache.getOrSet('key', fetchData, {
    strategy: CacheStrategy.CACHE_FIRST
});

Network-First

Try network first, fallback to cache.

const data = await cache.getOrSet('key', fetchData, {
    strategy: CacheStrategy.NETWORK_FIRST
});

Stale-While-Revalidate

Return cache immediately, update in background.

const data = await cache.getOrSet('key', fetchData, {
    strategy: CacheStrategy.STALE_WHILE_REVALIDATE
});

Network-Only

Always fetch from network, never use cache.

const data = await cache.getOrSet('key', fetchData, {
    strategy: CacheStrategy.NETWORK_ONLY
});

Cache-Only

Only use cache, never fetch from network.

const data = await cache.get('key', {
    strategy: CacheStrategy.CACHE_ONLY
});

Integration with RequestDeduplicator

import { CacheManager } from './modules/cache-manager/index.js';
import { RequestDeduplicator } from './modules/livecomponent/RequestDeduplicator.js';

const cache = CacheManager.create();
const deduplicator = new RequestDeduplicator();

// Use cache with request deduplication
async function fetchWithCache(url) {
    return await cache.getOrSet(url, async () => {
        // Check for pending request
        const pending = deduplicator.getPendingRequest('api', 'GET', { url });
        if (pending) {
            return await pending;
        }
        
        // Make request
        const promise = fetch(url).then(r => r.json());
        deduplicator.registerPendingRequest('api', 'GET', { url }, promise);
        
        return await promise;
    });
}

Use Cases

API Response Caching

const cache = CacheManager.create({
    defaultStrategy: CacheStrategy.STALE_WHILE_REVALIDATE,
    defaultTTL: 300000 // 5 minutes
});

async function getUsers() {
    return await cache.getOrSet('api:users', async () => {
        const response = await fetch('/api/users');
        return await response.json();
    });
}

Computed Value Caching

const cache = CacheManager.create();

function expensiveComputation(input) {
    // Expensive operation
    return input * 2;
}

async function getComputedValue(input) {
    const key = `computed:${input}`;
    return await cache.getOrSet(key, () => expensiveComputation(input), {
        ttl: 3600000 // Cache for 1 hour
    });
}

Cache Invalidation

// Invalidate all user-related cache when user updates
async function updateUser(userId, data) {
    await fetch(`/api/users/${userId}`, {
        method: 'PUT',
        body: JSON.stringify(data)
    });
    
    // Invalidate related cache
    await cache.invalidate(`user:${userId}`);
    await cache.invalidate('users:list');
}

Cache Warming

// Warm cache on page load
async function warmCache() {
    await cache.warm(['user:1', 'user:2', 'user:3'], async (key) => {
        const userId = key.split(':')[1];
        const response = await fetch(`/api/users/${userId}`);
        return await response.json();
    });
}

Best Practices

  1. Choose Appropriate Strategy - Use cache-first for static data, network-first for dynamic data
  2. Set Appropriate TTL - Balance freshness with performance
  3. Invalidate on Updates - Clear cache when data changes
  4. Use Cache Warming - Preload frequently accessed data
  5. Monitor Analytics - Track cache performance and adjust strategy

Browser Support

  • Chrome/Edge: 90+
  • Firefox: 88+
  • Safari: 14+
  • Mobile: iOS 14+, Android Chrome 90+

Required Features:

  • ES2020 JavaScript
  • IndexedDB (for persistent cache)
  • Promise support

Next: Continue with Phase 3 modules →