Skip to content

feat: tag-based invalidation, full Vary/credential eviction, and cache status header (v2.6.0) - #13

Merged
FranRuiz98 merged 1 commit into
masterfrom
feat/tag-invalidation-eviction-status
Aug 26, 2026
Merged

feat: tag-based invalidation, full Vary/credential eviction, and cache status header (v2.6.0)#13
FranRuiz98 merged 1 commit into
masterfrom
feat/tag-invalidation-eviction-status

Conversation

@FranRuiz98

Copy link
Copy Markdown
Owner

Implements the v2.6.0 feature set: complete invalidation plus observability.

Tag-based invalidation (EvictByTagAsync)

  • Responses are labeled with cache tags collected from the response headers named in CacheOptions.TagHeaderNames (Cache-Tag, Surrogate-Key, xkey — comma- and space-separated values both parse) or attached per request via CacheRequestPolicy.Tags.
  • Each tag maps to an index entry in the client's own ICacheStore (memory or distributed), listing the primary keys carrying it; EvictByTagAsync("products") sweeps them all, Vary variants included, then drops the index.
  • Tags are stored on the entry (CacheEntry.Tags) so every 304 refresh re-extends the index deadline — a repeatedly revalidated entry can't outlive its index.
  • Best-effort by design (read-merge-write, capped at 1024 keys/tag): an entry that falls out of the index expires via its own freshness rules and is never served incorrectly.

Explicit eviction sweeps Vary variants

  • Variant keys are now tracked on the primary marker (CacheEntry.TrackedKeys) as they are stored; EvictAsync follows the marker and removes them, closing the documented unreachable-but-alive trade-off.
  • RFC 9111 §4.4 invalidation deliberately keeps its read-free single-remove (its marker removal already makes variants unreachable; the extra round-trip per unsafe request isn't worth it).

Credential-scoped eviction

  • EvictAsync(uri, authorization) resolves the credential-scoped key authenticated GETs store under with AuthorizationCaching enabled, closing the 2.4 limitation. New IStampedeHttpCache members ship as default interface methods (throwing NotSupportedException) so pre-2.6 custom implementations keep compiling.

Cache status header (X-Stampede-Cache)

  • Every response the caching layer handles reports how it was obtained: HIT / MISS / STALE / REVALIDATED; the coalescer stamps COALESCED on waiters that shared another caller's in-flight origin call (survives the caching layer's miss marking).
  • Constants + typed accessor on StampedeCacheStatus; stored entries strip the header, so a replayed hit always reports its own status.

Compatibility

  • CacheEntry gains TrackedKeys and Tags (both default []; pre-2.6 serialized entries deserialize cleanly — covered by tests).
  • All features are additive and off by default except the status header, which is always emitted on cache-handled responses.

Tests

  • 26 new tests (463 total, all passing; suite run 3× for concurrency stability). Build clean with -warnaserror.

🤖 Generated with Claude Code

… cache status header

- IStampedeHttpCache.EvictByTagAsync: responses labeled via CacheOptions.TagHeaderNames
  (Cache-Tag, Surrogate-Key, xkey conventions; comma- and space-separated) or
  CacheRequestPolicy.Tags are indexed per tag in the client's own ICacheStore, so one
  call evicts every tagged entry, Vary variants included. 304 refreshes re-extend the
  index deadline so long-revalidated entries stay reachable by tag.
- EvictAsync now sweeps Vary variants: variant keys are tracked on the primary marker
  (CacheEntry.TrackedKeys) at store time and removed on explicit eviction, closing the
  documented unreachable-but-alive trade-off. RFC 9111 4.4 invalidation unchanged.
- EvictAsync(uri, authorization): credential-scoped eviction for entries stored under
  AuthorizationCaching, resolving the same key the authenticated GET stored under. New
  interface members ship as default interface methods for pre-2.6 implementations.
- X-Stampede-Cache response header (StampedeCacheStatus): HIT / MISS / STALE /
  REVALIDATED on every response the caching layer handles, COALESCED stamped by the
  coalescer on waiters; never persisted into stored entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@FranRuiz98
FranRuiz98 merged commit 131102b into master Aug 26, 2026
3 checks passed
@FranRuiz98
FranRuiz98 deleted the feat/tag-invalidation-eviction-status branch August 26, 2026 18:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant