Advance the watermark monotonically after the source mutation commits.
The adapter supplies a nonnegative safe-integer Date.now() sample to
INVALIDATE_CACHE_SCRIPT as ARGV[2]; futureBufferMs is ARGV[1].
Reuse that sample through retries within one adapter invocation.
Its TTL is at least two hours and otherwise derived to outlive the future
buffer plus the maximum tracked-value TTL. Longer or persistent existing
markers are preserved. A wrong-type watermark is repaired; any other Redis
read error surfaces without replacing prior state.
Read a DialCache Redis frame. Hits return the decoded serializer payload
with the frame header's creation time. Implementations must use
decodeRedisReadResult (untracked) or decodeTrackedRedisReadResult
(tracked) from dialcache/redis-protocol, or preserve their exact behavior.
Raw values are Redis bulk strings (Buffer) or null. A missing value, a
frame shorter than the version/timestamp/encoding header, or an
unsupported frame version is a cache miss. A missing tracked watermark
is the zero baseline. A tracked read misses when a present watermark is
not a nonnegative safe-integer decimal or is greater than or equal to the
frame's creation time. In other words, createdAt <= watermark is fenced.
Unsupported payload encodings and non-bulk runtime replies are payload
protocol errors rather than misses.
Tracked implementations must read the value and watermark atomically from one authoritative snapshot; replica lag must not hide an invalidation.
Misses are RedisReadMiss { kind: "miss", reason, observedWatermarkMs? }.
Attach observedWatermarkMs only when the same tracked snapshot contained
a present, valid numeric watermark. DialCache validates the fence, drops it
on untracked keys, and records any unrecognized result or reason as an
unclassified miss. Adapters that attach an observed watermark must also
honor RedisWriteRequest.createdAtMs when supplied.
A returned frame's payload is transferred to DialCache. A returned Buffer must remain stable and must not be mutated, pooled, or reused after this method settles; DialCache may retain it for source-error recovery or best-effort shadow work. Adapters that recycle response storage must return a dedicated Buffer.
Optionalcontext: RedisReadContextWrite a DialCache Redis frame using the dialcache/redis-protocol
encoders, or preserve their exact behavior.
All writes are one native SET valueKey frame PX cacheTtlMs whose frame
comes from encodeRedisFrame. Honor request.createdAtMs exactly when it
is supplied; callers that omit it may be stamped from the adapter's client
clock.
DialCache uses every frame's decoded createdAtMs for future-time
rejection and logical-age enforcement, and for shadow and stale-recovery
value-age observations, so writers must stamp real client time, not a
constant.
Tracked and untracked writes use the same complete-frame SET. Core caps a tracked value's physical TTL at one hour. Under the documented clock-skew and in-flight-work bounds, invalidation markers outlive every value they fence, so writers never read, create, or extend watermarks.
Caller-owned semantic Redis boundary. DialCache borrows this client and does not create, connect, drain, dispose, or close it.
Clients must use finite application-defined connection, retry, reconnect, offline-queue, dispatch, and response budgets to bound underlying resource lifetime. DialCache additionally bounds how long it waits for reads, but does not claim server-side cancellation. A command that times out after dispatch may still have executed, so adapters must document their queue-removal and ambiguous-write semantics.
Tracked invalidation also requires the Redis deployment to preserve watermark keys for their derived TTL. Losing a watermark through eviction, failover, restore, or external deletion removes its prior read-time invalidation fence.