HTTP-Semantics Aware Caching: ETag/304 Revalidation, stale-while-revalidate, Cache Tags & Inspector
Summary
Upgrade GhostCache from time-only TTL to full HTTP-aware caching: parse and honor Cache-Control, support conditional requests (ETag/Last-Modified → 304), add stale-while-revalidate/stale-if-error, introduce cache tags for targeted invalidation, and ship a tiny DevTools-style inspector API for visibility.
Motivation
Many APIs expose validators and caching hints (ETag, Last-Modified, Cache-Control, Vary). Today we rely primarily on TTL. Supporting HTTP semantics improves correctness, reduces bandwidth, and enables instant UI while background-refreshing.
Goals
-
Conditional Revalidation
- Store ETag / Last-Modified from responses.
- On refresh, send
If-None-Match / If-Modified-Since; treat 304 as a fast cache hit (update age/headers).
-
Cache-Control Parsing
- Respect
max-age, s-maxage, no-store, no-cache, must-revalidate, stale-while-revalidate, stale-if-error.
- Normalize with existing
ttl (explicit ttl overrides headers unless respectHeaders: true).
-
Stale While Revalidate (SWR)
- Serve stale immediately when within
stale-while-revalidate window, then refresh in background and update store; expose a hook/callback for “refreshed” events.
-
Stale-If-Error
- If network/5xx during refresh and stale exists within
stale-if-error, serve stale and surface a soft warning event/metric.
-
Cache Key Normalization
- Option to include/exclude query params, headers, and method; support a custom
keyFn(req) to unify semantically identical requests.
-
Cache Tags & Batch Invalidation
- Allow setting
tags: string[] per entry; expose invalidateByTag("user:42") to drop related keys (useful after POST/PUT/DELETE).
-
Inspector / DevTools Hooks
-
Axios & fetch Parity
- Implement revalidation and header handling for both adapters.
Non-Goals
- Full HTTP proxy behavior or full RFC 9111 edge cases.
- Persisted header normalization across all custom adapters beyond documented subset.
API Proposal
enableGhostCache({
ttl: 60_000,
respectHeaders: true, // NEW: honor Cache-Control / validators
swr: true, // NEW: enable stale-while-revalidate behavior
keyFn: (req) => string, // NEW: optional custom cache key builder
});
setCache("user/42", data, { tags: ["user:42"] }); // NEW: tags
invalidateByTag("user:42"); // NEW
const info = GhostCacheInspector.getEntry(key); // NEW
GhostCacheInspector.on("revalidate", (e) => { ... }); // NEW
Design Notes
-
Storage Layout: extend stored metadata to { body, status, headers, etag, lastModified, cacheControl, tags, createdAt, lastValidatedAt }.
-
Revalidation Flow:
- Lookup entry; if fresh → hit.
- If stale and
swr → return stale immediately; kick off background fetch with If-None-Match / If-Modified-Since.
- On 304 → update timestamps/headers; on 200 → replace body/headers.
- On error and
stale-if-error window → serve stale, emit event.
-
Key Normalization: default includes method + URL + sorted query; exclude transient headers unless varyHeaders: ["Accept-Language"] is set.
-
Security/Privacy: never cache Authorization-bearing responses unless cacheAuth: true and private: true are set; scrub PII headers from stored metadata by default.
Acceptance Criteria
Testing Plan
-
Unit tests covering:
- 200 → store validators; later 304 → metadata refresh only.
max-age/no-cache/SWR/stale-if-error branches.
- Tag invalidation correctness.
- Key normalization edge cases (query order, header variations).
-
Integration tests:
- Axios and fetch parity using a mock HTTP server returning ETag/Last-Modified and varying directives.
-
Performance:
- Ensure overhead for header parsing and background revalidation is negligible (<1ms average per call in Node 18+).
HTTP-Semantics Aware Caching: ETag/304 Revalidation,
stale-while-revalidate, Cache Tags & InspectorSummary
Upgrade GhostCache from time-only TTL to full HTTP-aware caching: parse and honor
Cache-Control, support conditional requests (ETag/Last-Modified → 304), addstale-while-revalidate/stale-if-error, introduce cache tags for targeted invalidation, and ship a tiny DevTools-style inspector API for visibility.Motivation
Many APIs expose validators and caching hints (ETag,
Last-Modified,Cache-Control,Vary). Today we rely primarily on TTL. Supporting HTTP semantics improves correctness, reduces bandwidth, and enables instant UI while background-refreshing.Goals
Conditional Revalidation
If-None-Match/If-Modified-Since; treat 304 as a fast cache hit (update age/headers).Cache-ControlParsingmax-age,s-maxage,no-store,no-cache,must-revalidate,stale-while-revalidate,stale-if-error.ttl(explicitttloverrides headers unlessrespectHeaders: true).Stale While Revalidate (SWR)
stale-while-revalidatewindow, then refresh in background and update store; expose a hook/callback for “refreshed” events.Stale-If-Error
stale-if-error, serve stale and surface a soft warning event/metric.Cache Key Normalization
keyFn(req)to unify semantically identical requests.Cache Tags & Batch Invalidation
tags: string[]per entry; exposeinvalidateByTag("user:42")to drop related keys (useful after POST/PUT/DELETE).Inspector / DevTools Hooks
Optional tiny overlay API:
getEntry(key),listEntries({tag}),stats()(hits/misses/revalidations).onHit,onMiss,onRevalidate,onInvalidate.Axios & fetch Parity
Non-Goals
API Proposal
Design Notes
Storage Layout: extend stored metadata to
{ body, status, headers, etag, lastModified, cacheControl, tags, createdAt, lastValidatedAt }.Revalidation Flow:
swr→ return stale immediately; kick off background fetch withIf-None-Match/If-Modified-Since.stale-if-errorwindow → serve stale, emit event.Key Normalization: default includes method + URL + sorted query; exclude transient headers unless
varyHeaders: ["Accept-Language"]is set.Security/Privacy: never cache
Authorization-bearing responses unlesscacheAuth: trueandprivate: trueare set; scrub PII headers from stored metadata by default.Acceptance Criteria
Cache-Controldirectives respected whenrespectHeaders: true.stale-if-errorreturns stale on refresh failure within window.invalidateByTag()removes affected entries across adapters.getEntry,listEntries,stats, and event hooks.fetchandaxios; 95%+ unit test coverage for new logic.Testing Plan
Unit tests covering:
max-age/no-cache/SWR/stale-if-errorbranches.Integration tests:
Performance: