Skip to content

feat: enable shadowing for untracked caches - #122

Merged
lan17 merged 1 commit into
mainfrom
agent/untracked-shadowing
Aug 5, 2026
Merged

feat: enable shadowing for untracked caches#122
lan17 merged 1 commit into
mainfrom
agent/untracked-shadowing

Conversation

@lan17

@lan17 lan17 commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • extend the existing detached Redis shadow path to untracked cache keys
  • warm a clean untracked shadow miss with the caller-accepted source value using the ordinary TTL write
  • preserve tracked watermark behavior and the existing shadow configuration, metrics, outcomes, deadlines, and capacity limits
  • document the rollout impact and add unit plus real Redis/Valkey coverage

Motivation

Shadowing was gated on trackForInvalidation: true, so an otherwise valid untracked Redis policy with a nonzero shadow.ramp did nothing. That prevented teams from validating and warming ordinary Redis keys before increasing their serving ramp.

The intended contract is:

normal caller path -> source result S
                  \-> detached Redis C0
                        hit  -> existing compare / C1 confirmation flow
                        miss -> same-mode Redis write(S)

The detached path never serves the caller. When remote serving is ramped down, it reuses the caller's already-running, successfully accepted source result instead of calling the loader again.

Architecture and correctness

This reuses the existing mechanisms rather than adding another public concept:

  • scheduleShadowValidation no longer rejects untracked keys.
  • The internal shadow read helper delegates to the existing key-sensitive Redis read path.
  • The existing shadow fill helper delegates to the normal key-sensitive Redis write path.
  • No public API, configuration field, metric, outcome, adapter branch, Lua script, key format, or cache layer changes.

The key's established consistency mode remains authoritative:

  • Tracked keys: watermark-aware primary reads and watermark-fenced writes.
  • Untracked keys: ordinary one-key reads and TTL-based last-writer-wins writes, with no invalidation watermark or shadow-specific primary guarantee.

The initial clean-miss read and detached fill are not atomic. An untracked fill can overwrite a newer concurrent value and remain until expiry; the README now states that boundary explicitly. Existing tracked invalidation fencing is unchanged.

Compatibility and rollout

Calls with omitted shadow configuration or shadow.ramp: 0 are unchanged.

This is an intentional behavior change for untracked keys that already have all of the following:

  • a valid Redis policy and TTL
  • a nonzero effective shadow.ramp
  • an observable metrics.shadowValidation hook
  • normal traversal reaching the Redis layer

Those keys now generate the opted-in source/Redis validation traffic and may fill clean misses. Deployments that configured a nonzero shadow ramp while relying on the previous tracked-only eligibility rule should set it to 0 before upgrading if they do not want that work.

Test coverage

The added coverage proves:

  • served untracked hits run comparison and C1 confirmation without watermark requests
  • ramped-down untracked hits validate without serving or repairing Redis
  • clean untracked misses fill Redis without creating a watermark
  • a later serving-ramp increase returns the warmed value without another source call
  • tracked and untracked fills retain their respective request shapes
  • omitted or zero shadow ramps remain inert for untracked keys

Validation

Run with Node 22.22.0:

  • corepack pnpm check — 408 unit tests, coverage thresholds, typecheck, build/declarations, and packed ESM/CJS consumers
  • corepack pnpm test:integration — 101 Redis 6.2 / Valkey 8 integration tests across node-redis and GLIDE
  • corepack pnpm benchmark:request-local — all 10 semantic scenarios passed
  • corepack pnpm audit --prod --audit-level high — no known production vulnerabilities
  • git diff --check
  • two fresh independent reviews with no findings

@lan17
lan17 marked this pull request as ready for review August 5, 2026 07:16
@lan17
lan17 merged commit 7231e3e into main Aug 5, 2026
5 checks passed
@lan17
lan17 deleted the agent/untracked-shadowing branch August 5, 2026 18:08
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