- 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
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 strategyconfig.defaultTTL- Default time-to-live in millisecondsconfig.maxMemorySize- Maximum items in memory cacheconfig.enableIndexedDB- Enable IndexedDB persistenceconfig.indexedDBName- IndexedDB database nameconfig.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 keyoptions.strategy- Caching strategy overrideoptions.ttl- Time-to-live override
Returns: Promise<any | null>
cache.set(key, value, options)
Set value in cache.
Parameters:
key- Cache keyvalue- Value to cacheoptions.strategy- Caching strategyoptions.ttl- Time-to-live
Returns: Promise<void>
cache.getOrSet(key, computeFn, options)
Get value from cache or compute and cache it.
Parameters:
key- Cache keycomputeFn- Function to compute value if not cachedoptions- 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 keyscomputeFn- 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
- Choose Appropriate Strategy - Use cache-first for static data, network-first for dynamic data
- Set Appropriate TTL - Balance freshness with performance
- Invalidate on Updates - Clear cache when data changes
- Use Cache Warming - Preload frequently accessed data
- 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 →