Skip to content

feat(cache): add unified Cache#7236

Open
tomas-zijdemans wants to merge 11 commits into
denoland:mainfrom
tomas-zijdemans:cache
Open

feat(cache): add unified Cache#7236
tomas-zijdemans wants to merge 11 commits into
denoland:mainfrom
tomas-zijdemans:cache

Conversation

@tomas-zijdemans

Copy link
Copy Markdown
Contributor

This PR replaces LruCache and TtlCache with a single Cache<K, V> that unifies LRU eviction, TTL expiration, stale-while-revalidate, and load-through (getOrLoad).

The existing caches extend Map, so inherited methods bypass LRU/TTL logic entirely. Both subclass Map, making it structurally impossible to compose LRU with TTL.

Cache<K, V> uses composition over inheritance: it owns a Map for storage and delegates to IndexedHeap for deadline-ordered expiration. Mode is determined by options, not class choice, and a discriminated union on CacheOptions makes illegal combinations compile-time errors.

Beyond fixing the structural issues, this introduces capabilities that didn't exist before:

  • Combined LRU + TTL in a single cache
  • Renames the base type to CacheLike, a more natural type name
  • getOrLoad(key, loader) with automatic in-flight deduplication
  • Stale-while-revalidate with background refresh, error handling, and configurable soft/hard TTL thresholds
  • Per-entry TTL overrides and sliding expiration
  • Single heap-driven timer replacing per-entry setTimeouts
  • Hit/miss/eviction stats, typed ejection reasons, and Symbol.dispose

Since @std/cache is still experimental (0.2.2), this is the right time to make a clean break before stabilization locks things in.

Bonus: The new Cache has significant performance improvements for real-life workflows (e.g. in my testing, write-heavy workloads (set, eviction) are 4-22x faster. hot-key reads are 55x faster thanks to a linked-list)


Note

Recreates #7082, which was closed automatically when I accidentally deleted the head fork. The branch is identical to the original PR head.

tomas-zijdemans and others added 11 commits April 22, 2026 14:13
Introduces a single `Cache` class that subsumes both `LruCache` and
`TtlCache` into a configuration-driven API (maxSize, ttl, sliding
expiration, stale-while-revalidate refresh, and onRemove). The new
implementation delegates expiration tracking to `IndexedHeap` from
`@std/data-structures/unstable-indexed-heap` for O(log n) evictions.

- Add cache/cache.ts and cache/cache_test.ts
- Remove cache/lru_cache.ts, cache/ttl_cache.ts and their tests
- Update cache/memoize.ts doc to reference Cache
- Update cache/mod.ts and cache/deno.json exports

Made-with: Cursor
@github-actions github-actions Bot added the cache label Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant