Beim Kombinieren von Cache und Remote-Fetch neigt die Logik dazu, sich zu vermischen. Das Kapseln in einer Orchestrierungsfunktion trennt die Cache-Hit- und Cache-Miss-Pfade sauber und zentralisiert gleichzeitig die Metrikinstrumentierung und die Delegierung von Nebeneffekten.
Typdefinitionen
interface CacheProvider<T> { get(key: string): Promise<T | undefined>; set(key: string, value: T): Promise<void>;}
interface RemoteProvider<T> { fetch(key: string): Promise<T>;}
interface MetricsReporter { recordCacheHit(key: string, latencyMs: number): void; recordCacheMiss(key: string): void; recordFetchLatency(key: string, latencyMs: number): void; recordOutcome(key: string, outcome: 'success' | 'error', latencyMs: number): void;}Orchestrierungsfunktion
async function orchestrate<T>( key: string, cache: CacheProvider<T>, remote: RemoteProvider<T>, metrics: MetricsReporter,): Promise<T> { const start = performance.now();
// Schneller Pfad: Cache-Hit const cached = await cache.get(key); if (cached !== undefined) { metrics.recordCacheHit(key, performance.now() - start); return cached; }
// Langsamer Pfad: Live-Fetch metrics.recordCacheMiss(key); const fetchStart = performance.now(); try { const data = await remote.fetch(key); metrics.recordFetchLatency(key, performance.now() - fetchStart);
// Nebeneffekt nach außen delegiert — fire and forget void cache.set(key, data); metrics.recordOutcome(key, 'success', performance.now() - start); return data; } catch (error) { metrics.recordOutcome(key, 'error', performance.now() - start); throw error; }}Verwendungsbeispiel
const result = await orchestrate( 'user:42', redisCache, userApiClient, datadogMetrics,);Erläuterung
- Schneller Pfad: Bei einem Cache-Treffer wird sofort zurückgegeben — der Remote-Dienst wird nie aufgerufen.
- Langsamer Pfad: Fallback zum Remote-Dienst nur bei einem Cache-Miss. Nach dem Abrufen wird der Cache als Fire-and-Forget-Nebeneffekt aktualisiert.
- Metriken: Cache-Hits, -Misses, Fetch-Latenz und das Endergebnis werden vollständig instrumentiert. Die Delegierung an
MetricsReporterentkoppelt den Orchestrator von Datadog, Prometheus oder einem anderen Logging-Backend. - Nebeneffekt-Delegierung: Cache-Schreibvorgänge und Metrikaufrufe werden nach außen verlagert. Das macht die Orchestrierungsfunktion einfach testbar und erlaubt einen unkomplizierten Austausch der Implementierungen.
Anwendungsgebiete
Dieses Muster eignet sich besonders für:
- Importer: Bereits verarbeitete Datensätze mit einer schnellen Cache-Prüfung überspringen, bevor die Quelle aufgerufen wird.
- Datenanreicherungs-Jobs: Bereits vollständige Entitäten nicht erneut anreichern.
- Synchronisierungs-Handler: Doppelte Abrufe verhindern und gleichzeitig Unterschiede mit Metriken verfolgen.
- Aufwändige UI-Aktionen: Den Remote-Aufruf nur beim ersten Laden ausführen; nachfolgende Anfragen aus dem Cache bedienen.
Da CacheProvider, RemoteProvider und MetricsReporter als Interfaces definiert sind, kann jede Kombination von Implementierungen — Redis/in-memory, REST/gRPC, Datadog/StatsD — eingebunden werden, ohne die Orchestrierungslogik zu ändern.
hsb.horse