Docs/cachingv1.0.0-rc.1

CacheManager

CacheManager is the central coordinator for all caching operations. It owns a map of named ICacheProvider instances and exposes a unified API for reading, writing, and invalidating cached values. A single global instance is available via getGlobalCacheManager().

Key Concepts

  • Providers map. Multiple backends (memory, Redis, CDN) can be registered under their strategy name. A request for strategy 'auto' or an unknown name falls back to the 'memory' provider.
  • Tag index. When an entry is stored with tags, the manager records the tag → key mapping internally so that invalidate({ tags }) can remove all associated keys without querying every provider.
  • Event invalidation. setupEventInvalidation() registers a handler so that handleEvent(name, payload) can evict keys, patterns, or tags in response to domain events.
  • Auto TTL. When ttl: 'auto' is passed to getOrSet, the TTL is derived from the factory's compute duration: max(60, min(computeMs * 10, 3600)) seconds. This means expensive operations receive longer cache lifetimes automatically.

API Reference

Constructor

new CacheManager(options?: CacheManagerOptions)

CacheManagerOptions:

Field Type Default Description
defaultProvider CacheStrategy 'memory' Backend used when no strategy is specified
providers Map<string, ICacheProvider> — Pre-registered provider instances
aiEnabled boolean false Reserved for future AI-driven strategy selection
defaultTTL number 300 Fallback TTL in seconds

Primary Methods

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

The main caching primitive. Checks the cache first; on a miss, calls factory(), stores the result, then returns it.

options: AICacheOptions & { strategy?: CacheStrategy }
Option Type Description
strategy CacheStrategy Override the default provider
ttl 'auto' | number TTL in seconds, or 'auto'
tags string[] Tags for grouped invalidation

get<T>(key, strategy?): Promise<T | null>

Returns the cached value or null.

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

Stores a value. Options include ttl, tags, priority, compress, and strategy.

delete(key): Promise<boolean>

Removes the key from all registered providers. Returns true if at least one provider deleted it.

invalidate(options: InvalidateOptions): Promise<void>

Evicts by key, glob pattern, or tags.

interface InvalidateOptions {
  key?:     string;     // exact key
  pattern?: string;     // wildcard pattern: 'user:*'
  tags?:    string[];   // tag names
}

clear(pattern?): Promise<void>

Clears all providers (optionally filtered by pattern). Also resets the internal tag index when no pattern is given.

getStats(): Promise<CacheStats & { byProvider: Map<string, CacheStats> }>

Returns aggregated statistics plus a per-provider breakdown.

CacheStats:

Field Type Description
hits number Total cache hits
misses number Total cache misses
hitRate number hits / (hits + misses) (0–1)
size number Approximate byte size
keys number Number of live entries

prewarm(predictions: CachePrediction[]): Promise<void>

Calls getOrSet for each prediction with confidence > 0.7.

setupEventInvalidation(config: EventInvalidationConfig): void

Registers a mapping from a domain event name to keys, tags, or a pattern to invalidate.

handleEvent(eventName, payload): Promise<void>

Triggers all invalidations registered for eventName.

registerProvider(name, provider): void

Adds or replaces a named provider at runtime.

Global Manager Helpers

getGlobalCacheManager(): CacheManager    // lazy-creates a default manager
setGlobalCacheManager(manager): void     // replace the global instance
resetGlobalCacheManager(): void          // set to null (useful in tests)

Basic Usage

import {
  CacheManager,
  setGlobalCacheManager,
} from '@tagna/udiot';

// Configure once at startup
const cache = new CacheManager({ defaultTTL: 600 });
setGlobalCacheManager(cache);

// Use in a service
const user = await cache.getOrSet(
  `user:${id}`,
  () => db.users.findById(id),
  { ttl: 300, tags: ['user', `user:${id}`] }
);

Common Patterns

Wrapping a database query

import { getGlobalCacheManager } from '@tagna/udiot';

async function getProduct(id: string) {
  const cache = getGlobalCacheManager();
  return cache.getOrSet(
    `product:${id}`,
    () => db.products.findById(id),
    { ttl: 120, tags: ['products', `product:${id}`] }
  );
}

Manual invalidation after an update

async function updateProduct(id: string, data: Partial<Product>) {
  const updated = await db.products.update(id, data);
  const cache = getGlobalCacheManager();
  await cache.invalidate({ tags: [`product:${id}`, 'products'] });
  return updated;
}

Printing stats

const stats = await cache.getStats();
console.log(`Hit rate: ${(stats.hitRate * 100).toFixed(1)}%`);
console.log(`Keys: ${stats.keys}, Size: ${stats.size} bytes`);
for (const [name, s] of stats.byProvider) {
  console.log(`  [${name}] hits=${s.hits} misses=${s.misses}`);
}

Integration Notes

  • getOrSet emits OpenTelemetry spans (cache.getOrSet) and increments cache.hit / cache.miss metrics automatically.
  • The 'auto' strategy resolves to the default provider at runtime; it does not yet invoke AICacheAnalyzer for routing decisions.
  • delete iterates all providers, so a key can be evicted from every tier in one call.

Pitfalls

  • Do not call resetGlobalCacheManager() in production code; it is intended only for test isolation.
  • Tag indexes live in memory within the manager instance. If you create multiple CacheManager instances each pointing at the same Redis backend, tag-based invalidation from one instance will not be visible to the other.
  • clear() without a pattern resets the tag index. After a full clear, previously tagged keys can no longer be invalidated by tag until they are re-written.
From the canonical UDIOT public documentation.Try it in the playground ↗