Skip to content

Exchange Rate Cache with TTL Eviction #518

Description

@Kingsman-99

Description

src/currencyConverter.ts fetches exchange rates on every invocation, making repeated conversions in a single invoice rendering session unnecessarily expensive and slow. Rates fetched from external oracles rarely change within a minute, so a time-to-live cache should store fetched rates and serve subsequent requests from memory until the TTL expires, with background refresh to avoid cold-fetch latency on expiry.

Technical Context

Add src/rateCache.ts. Integrates with src/currencyConverter.ts and any price oracle adapter. Implements a Map<string, { rate: number; fetchedAt: number }> store keyed by "${fromAsset}:${toAsset}". Uses src/cache.ts eviction patterns. Background refresh implemented with a setInterval owned by RateCache lifecycle methods start() / stop(). Ties into src/gracefulShutdown.ts pattern from src/index.ts.

Acceptance Criteria

  • RateCache.getRate(from, to): Promise<number> serves from cache when Date.now() - fetchedAt < ttlMs
  • On first fetch or cache miss, calls the configured rate-oracle function and stores the result with a timestamp
  • Background refresh fires at ttlMs * 0.8 to pre-warm the cache before expiry
  • invalidate(from, to) removes a specific pair; invalidateAll() clears the entire cache
  • Unit tests assert: cache hit (no oracle call), cache miss after TTL (oracle called once), background refresh (oracle called before expiry)
  • All CI checks (npm test, npm run build, ESLint/TypeScript) pass and the branch has no merge conflicts

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions