Generated with go doc -all from bae1e5e. Use your browser's Find command to locate a symbol.
package dialcache // import "github.com/lan17/DialCache/go"
Package dialcache provides explicitly enabled, layered caching with runtime
rollout, request coalescing, invalidation, stale recovery and shadow validation.
CONSTANTS
const (
// DefaultSourceTimeout bounds a source call when Operation.SourceTimeout is zero.
DefaultSourceTimeout = 60 * time.Second
// DefaultRemoteReadTimeout bounds a remote read unless an option or policy overrides it.
DefaultRemoteReadTimeout = 50 * time.Millisecond
// NoTimeout disables the source deadline for one operation.
NoTimeout time.Duration = -1
// MaxSupportedDuration is the longest TTL, recovery age or future buffer: 365 days.
MaxSupportedDuration = time.Duration(MaxSupportedDurationMS) * time.Millisecond
// MaxDeadline is the longest source or read deadline.
MaxDeadline = time.Duration(MaxDeadlineMS) * time.Millisecond
)
const DefaultCompressionThresholdBytes = 4096
const DefaultZstdLevel = 3
const InvalidationScript = `local function parse_safe_integer(raw)
if not string.match(raw, "^%d+$") then return nil end
local value = tonumber(raw)
if not value or value > 9007199254740991 then return nil end
return value
end
local future_buffer_ms = parse_safe_integer(ARGV[1])
if not future_buffer_ms or future_buffer_ms < 0 or future_buffer_ms > 31536000000 then
return redis.error_reply("ERR invalid DialCache future buffer")
end
local invalidated_at_ms = parse_safe_integer(ARGV[2])
if not invalidated_at_ms or invalidated_at_ms > 9007199254740991 - future_buffer_ms then
return redis.error_reply("ERR invalid DialCache invalidatedAtMs")
end
local proposed_watermark = invalidated_at_ms + future_buffer_ms
local raw_watermark = redis.pcall("GET", KEYS[1])
if type(raw_watermark) == "table" and raw_watermark.err then
if not string.match(raw_watermark.err, "^WRONGTYPE ") then return raw_watermark end
raw_watermark = false
end
local current_watermark = 0
if raw_watermark then
local parsed_watermark = parse_safe_integer(raw_watermark)
if parsed_watermark then current_watermark = parsed_watermark end
end
local watermark = math.max(current_watermark, proposed_watermark)
local current_ttl_ms = -2
if raw_watermark then current_ttl_ms = redis.call("PTTL", KEYS[1]) end
local desired_ttl_ms = math.max(7200000, watermark - invalidated_at_ms + 3600000 + 60000)
if current_ttl_ms > desired_ttl_ms then desired_ttl_ms = current_ttl_ms end
local encoded_watermark = string.format("%.0f", watermark)
if current_ttl_ms == -1 then
redis.call("SET", KEYS[1], encoded_watermark)
else
redis.call("SET", KEYS[1], encoded_watermark, "PX", desired_ttl_ms)
end
return 1`
InvalidationScript is the version-1 wire invalidation transition. Redis
Lua numbers exactly represent the accepted safe-integer domain. Invalid
arguments return before GET/repair; wrong-type keys alone are repairable
read failures.
const JSONUndefinedSentinel = "__dialcache_json_undefined_v1__"
const MaxDeadlineMS = int64(2147483647)
const MaxDecompressedBytes = 512 * 1024 * 1024
const MaxSafeInteger = uint64(9007199254740991)
const MaxSupportedDurationMS = int64(31536000000)
const MaxTrackedValueTTLMS = int64(3600000)
const ShadowLogKeyMaxBytes = 2048
const ShadowLogTruncationMarker = "...[truncated]"
const ShadowLogValueMaxBytes = 8192
VARIABLES
var Absent = absentValue{1}
var ErrInvalidOperation = errors.New("dialcache: invalid operation")
ErrInvalidOperation wraps operation validation failures other than policy.
var ErrInvalidOption = errors.New("dialcache: invalid option")
ErrInvalidOption wraps constructor option validation failures.
var ErrInvalidPolicy = errors.New("dialcache: invalid policy")
ErrInvalidPolicy wraps static policy validation failures.
var ErrNoRemote = errors.New("dialcache: a remote adapter is required")
ErrNoRemote reports maintenance that needs a remote adapter.
var ErrReservedUseCase = errors.New("dialcache: reserved use case \"watermark\"")
ErrReservedUseCase reports the reserved use case "watermark".
var ErrUseCaseRegistered = errors.New("dialcache: use case is already registered")
ErrUseCaseRegistered reports a second Cached registration of a use case.
var ErrValueType = errors.New("dialcache: cached value has a different type than requested")
ErrValueType reports a shared in-process value of a different Go type.
FUNCTIONS
func Cached[T, Arg any](cache *Cache, op Operation[T], selectKey func(Arg) (Identity, error), source func(context.Context, Arg) (T, error)) (func(context.Context, Arg) (T, error), error)
Cached registers a use case once and returns its typed read-through
function. The key selector runs only for an enabled call and supplies the
ID and Args; KeyType, UseCase, Tracked and Namespace come from op.Identity.
The static policy and source timeout are captured at registration.
func CeilSupportedCacheTTLMS(value float64) (int64, error)
CeilSupportedCacheTTLMS is the adapter-level duration boundary. Fractional
milliseconds round up, before checking the positive, 365-day limit.
func Cohort(logical, discriminator string) float64
Cohort preserves FNV-1a over UTF-16 code units, including surrogate pairs.
func EncodeFrame(frame Frame) ([]byte, error)
EncodeFrame accepts only the writer timestamp domain. DecodeFrame retains
uint64 precision and leaves the additional safe-timestamp check to the core.
func FailureIsolatedObserver(observer func(Event) error) func(Event)
FailureIsolatedObserver adapts a fallible exporter for WithObserver.
Neither a returned error nor a panic may replace a source result or start
cache work.
func GetOrLoad[T any](ctx context.Context, c *Cache, op Operation[T], load func(context.Context) (T, error)) (T, error)
GetOrLoad executes one inline loader through the cache chain without
registering its use case. Outside an enabled scope it calls load directly.
Returned in-memory values are shared and must be treated as immutable.
func IsAbsent(value any) bool
func NormalizeArgs(args map[string]any) ([][2]string, error)
NormalizeArgs omits Absent, converts the supported scalar domain using the
JavaScript String rules, and orders names lexicographically by UTF-16 units.
Arbitrary precision integers use big.Int; objects and arrays are rejected.
func PreviewShadowLogKey(value string) string
func Ptr[T any](v T) *T
Ptr returns a pointer to v, for optional Policy and PolicyOverlay leaves.
func ReadBudget(ctx context.Context) (time.Duration, bool)
ReadBudget reports the remote read deadline attached to an adapter context.
func SemanticEqual(left, right any) bool
SemanticEqual is strict deep equality for the portable value domain:
numbers are one IEEE-754 type, NaN equals NaN, signed zeros differ, object
key order is irrelevant, and Absent differs from null. Byte payloads remain
typed bytes.
func ValidatePolicy(p Policy) error
ValidatePolicy checks a static policy; failures wrap ErrInvalidPolicy.
func ValidateRedisInvalidationReply(reply any) error
func ValidateRedisSetReply(reply any) error
func ValidateTimestampMS(value float64) (uint64, error)
TYPES
type Cache struct {
// Has unexported fields.
}
Cache is one DialCache instance: a process-local LRU, coalescing table,
shadow slots and use case registry shared by every value type.
func MustNew(opts ...Option) *Cache
MustNew is New for configuration known to be valid; it panics otherwise.
func New(opts ...Option) (*Cache, error)
New constructs a cache. Options are applied in order; an invalid option
returns an error wrapping ErrInvalidOption.
func (c *Cache) Disable(ctx context.Context) context.Context
Disable returns a context whose cached operations pass straight through to
their sources. Enabling again inside it rejoins the surrounding live scope.
func (c *Cache) Enable(ctx context.Context) (context.Context, func())
Enable returns a context in which cached operations participate, and the
function that closes that request scope. Call it when the request's work
is complete, typically with defer: it ends the request memo lifetime and
prevents late publication into it. A context enabled inside a live scope
shares that scope, and its close function does nothing. Retaining the
context after close does not keep caching enabled. Context cancellation
remains an application and source concern.
func (c *Cache) GetCoalescingState() CoalescingState
GetCoalescingState reports actual process leaders, followers and the oldest
leader's age for this instance.
func (c *Cache) Invalidate(ctx context.Context, identity Identity, futureBuffer time.Duration) (err error)
Invalidate raises the remote watermark for every tracked value of the entity
named by identity's KeyType and ID, so frames stamped at or before the
invalidation plus futureBuffer are no longer served. It requires a remote
adapter and returns its error. Local entries expire by TTL.
func (c *Cache) IsEnabled(ctx context.Context) bool
IsEnabled reports whether operations with ctx participate in caching.
func (c *Cache) WithDisabled(ctx context.Context, fn func(context.Context) error) error
WithDisabled runs fn with caching disabled.
func (c *Cache) WithEnabled(ctx context.Context, fn func(context.Context) error) error
WithEnabled runs fn inside an enabled scope that closes when fn returns.
type CallbackPanicError struct{ Value any }
func (e *CallbackPanicError) Error() string
type Clock interface {
WallMS() int64
ElapsedMS() int64
}
Clock separates wall timestamps from elapsed-time expiration and deadlines.
type CoalescingState struct{ Process ProcessCoalescingState }
type Codec[T any] interface {
Encode(T) (Payload, error)
Decode(Payload) (T, error)
}
Codec borrows immutable payloads. Every Decode must produce an independent
value.
type CompressionConfig struct {
ThresholdBytes int
Level int
}
func ResolveCompressionConfig(config *CompressionConfig) (CompressionConfig, error)
type CompressionReadResult struct {
Payload Payload
Outcome string
}
func DecompressPayload(payload Payload, limit ...int) CompressionReadResult
type CompressionWriteResult struct {
Payload Payload
Outcome string
OriginalBytes, StoredBytes int
}
func CompressPayload(payload Payload, config CompressionConfig, limit ...int) (CompressionWriteResult, error)
type ContextCodec[T any] interface {
EncodeContext(context.Context, T) (Payload, error)
DecodeContext(context.Context, Payload) (T, error)
}
type DatadogMetrics struct {
// Has unexported fields.
}
func NewDatadogMetrics(options DatadogMetricsOptions) (*DatadogMetrics, error)
func (adapter *DatadogMetrics) ObserveEvent(event Event) error
type DatadogMetricsOptions struct {
Client DogStatsDClient
ObservationMetricType string
Namespace string
NamespaceSet bool // distinguish an explicitly empty namespace from omission
}
type DeferredExecutor interface{ Defer(func()) }
DeferredExecutor controls detached work admission without changing its
rules.
type DogStatsDClient interface {
Increment(name string, value float64, tags map[string]string) error
Histogram(name string, value float64, tags map[string]string) error
Distribution(name string, value float64, tags map[string]string) error
}
DogStatsDClient leaves transport, buffering, flushing and ownership with
the caller. Both observation methods are required, matching the TypeScript
adapter.
type Event struct {
Kind string
Scope string
Key string
Data map[string]any
Seconds float64
Bytes int64
Outcome string
}
Event records public diagnostics; Data contains the backend-neutral labels.
type FallbackTimeoutError struct {
UseCase string
Timeout time.Duration
}
func (e *FallbackTimeoutError) Error() string
type Frame struct {
CreatedAtMS uint64
Binary bool
Payload []byte
}
type Identity struct {
Namespace string `json:"namespace"`
KeyType string `json:"keyType"`
ID string `json:"id"`
UseCase string `json:"useCase"`
Tracked bool `json:"trackForInvalidation"`
Args [][2]string `json:"args"`
}
Identity is an already normalized logical identity. Ordered arguments retain
caller order; normalization of host-language objects is a separate profile.
func (id Identity) Keys() (logical, value, watermark string, err error)
func (id *Identity) UnmarshalJSON(raw []byte) error
UnmarshalJSON rejects isolated UTF-16 escapes before encoding/json replaces
them. The Go API uses Unicode scalar strings; this is its fixture boundary.
type JSONCodec[T any] struct{}
JSONCodec implements the default JSON serializer over JSON-compatible
Go values and Absent. Object members holding Absent are omitted; array
elements holding Absent and nonfinite numbers become null. Big integers
and cycles are errors. Strings contain Unicode scalar values; JSON escapes
with unpaired UTF-16 surrogates are rejected. JSONCodec[any] preserves this
supported domain.
func (JSONCodec[T]) Decode(payload Payload) (T, error)
func (JSONCodec[T]) Encode(value T) (Payload, error)
type JSONMember struct {
Name string
Value any
}
JSONMember and JSONObject preserve object insertion order when
byte-identical JSON output matters. Integer-index names are emitted first,
as in JavaScript. A Go map has no insertion order; its other names are
emitted in UTF-16 order.
type JSONObject []JSONMember
type JSONPolicy map[string]any
JSONPolicy is a runtime overlay in the JSON configuration shape shared
with TypeScript: ttlSec and ramp layer maps, requestLocal, coalesce,
staleOnErrorMaxAgeSec, remoteReadTimeoutMs and shadow. Explicit null leaves
are invalid; Absent leaves inherit.
type Logger interface {
Debug(message string, details any)
Warn(message string, details any)
Error(message string, details any)
}
func FailureIsolatedLogger(logger Logger) Logger
type MetricsAdapter interface{ ObserveEvent(Event) error }
MetricsAdapter consumes only the bounded public diagnostic events. Event.Key
is never a metric label; exporting logical identities would add cardinality.
type MismatchDiffLevel string
MismatchDiffLevel is how much of the structural difference between the
compared values a confirmed-mismatch warning logs.
const (
// MismatchDiffOff logs no difference.
MismatchDiffOff MismatchDiffLevel = "off"
// MismatchDiffPaths logs the RFC 6901 JSON Pointers of the differing fields.
MismatchDiffPaths MismatchDiffLevel = "paths"
// MismatchDiffValues logs those pointers with the cached and source values
// at each one.
MismatchDiffValues MismatchDiffLevel = "values"
)
type MismatchEntry struct {
Path string
Cached, Source any
}
MismatchEntry is one differing field of a confirmed shadow mismatch: an RFC
6901 JSON Pointer into the compared value and the value on each side there.
Absent omits a side the field does not have, as the built-in computation
does for a member present on one side only; set both sides to Absent when
only the location is known. A nil side is JSON null.
A side renders as JSONCodec writes it, except that a value implementing
json.Marshaler, json.RawMessage included, renders at any depth as its
MarshalJSON output parsed back, so a type that redacts itself stays redacted
in diffJson. As in encoding/json, a pointer's MarshalJSON runs only for
an addressable value, such as a slice element. A side with no rendering
(a cycle, a *big.Int, a function, or a MarshalJSON that fails, panics or
returns output that is not JSON or holds a number outside double range) logs
a null diffJson with render_error and keeps the paths.
type MismatchLoggingPolicy struct {
// Value includes bounded native JSON of both compared values.
Value *bool
// Diff includes the differing fields at this level.
Diff *MismatchDiffLevel
}
MismatchLoggingPolicy selects what a confirmed-mismatch warning carries.
The warning is emitted when Value is true or Diff is above MismatchDiffOff.
Nil leaves inherit, and runtime overlays merge each leaf independently.
type Operation[T any] struct {
Identity Identity
// IdentityProvider computes the identity per invocation; Cached sets it from
// the key selector. A failing or reserved computed identity fails open.
IdentityProvider func() (Identity, error)
Policy Policy
// Codec overrides JSONCodec[T] for this operation's remote payloads.
Codec Codec[T]
// SourceTimeout bounds the source call. It must be whole milliseconds; zero
// means DefaultSourceTimeout and NoTimeout disables the deadline.
SourceTimeout time.Duration
// ShouldRecover replaces the instance recovery predicate for this operation.
ShouldRecover RecoveryPredicate
// Comparator decides shadow matches; nil compares with SemanticEqual.
Comparator func(cached, source T) (bool, error)
// MismatchDiff replaces the built-in JSON difference computation behind
// the mismatchPaths and diffJson fields of confirmed-mismatch warnings; it
// runs only when the resolved mismatch-logging diff level is above
// MismatchDiffOff. Inputs are borrowed snapshots. Like Comparator, it must
// be deterministic, side-effect-free, non-mutating and bounded. A returned
// error or panic logs null for the paths and the diff, without falling back
// to the built-in computation; a nil slice is an empty list.
MismatchDiff func(cached, source T) ([]MismatchEntry, error)
}
Operation describes one cached computation producing values of type T.
type Option func(*settings) error
Option configures New. Unset options keep the documented defaults.
func WithClock(clock Clock) Option
WithClock replaces the wall and elapsed clock, mainly for tests.
func WithCompression(config CompressionConfig) Option
WithCompression sets the write-side compression policy. Zero fields keep
the 4,096-byte threshold and zstd level 3. Reads always accept compressed
payloads.
func WithLocalCapacity(entries int) Option
WithLocalCapacity bounds process-local entries across every use case;
the default is 10,000. Zero disables local storage while keeping coalescing.
func WithLogger(logger Logger) Option
WithLogger replaces the standard logger. Logger failures are isolated.
func WithMetrics(adapter MetricsAdapter) Option
WithMetrics connects a MetricsAdapter such as the Prometheus or DogStatsD
adapter, isolating its errors and panics from cache and source results.
func WithNamespace(namespace string) Option
WithNamespace sets the logical key namespace; the default is "urn". An empty
namespace is permitted. Braces are reserved for Redis Cluster hash tags.
func WithObserver(observe func(Event)) Option
WithObserver receives every backend-neutral diagnostic event. Every
configured observer and metrics adapter receives each event; panics in an
observer are ignored.
func WithPolicyProvider(provider PolicyProvider) Option
WithPolicyProvider resolves a sparse runtime policy overlay once per enabled
invocation. A nil overlay inherits the operation's static policy.
func WithRecoveryOutcomes(hook func(Event)) Option
WithRecoveryOutcomes receives each stale recovery outcome.
func WithRemote(remote Remote) Option
WithRemote supplies the shared layer. Without it the cache is local only.
func WithRemoteReadTimeout(timeout time.Duration) Option
WithRemoteReadTimeout sets the instance remote read deadline in whole
milliseconds; the default is 50 ms. Policy can override it per use case.
func WithShadowCapacity(jobs int) Option
WithShadowCapacity bounds scheduled or running shadow jobs per instance;
the default is one. Excess jobs are dropped and reported.
func WithShadowOutcomes(hook func(Event)) Option
WithShadowOutcomes receives each shadow validation verdict and enables
shadow admission; without a hook no shadow work is scheduled.
func WithStaleRecovery(predicate RecoveryPredicate) Option
WithStaleRecovery sets the instance default for which source errors may
serve a retained stale value. Omitted, only FallbackTimeoutError qualifies.
func WithoutCompression() Option
WithoutCompression stores every payload uncompressed. Reads still decompress
marked payloads.
type Payload struct {
Bytes []byte
Binary bool
}
func EscapeRawPayload(payload Payload) Payload
type Policy struct {
// RequestLocal memoizes successful values for the enabled scope's lifetime.
RequestLocal bool
// LocalTTL and RemoteTTL enable a layer with an insertion TTL in whole seconds.
LocalTTL time.Duration
RemoteTTL time.Duration
// LocalRamp and RemoteRamp are cohort percentages from 0 through 100; nil means 100.
LocalRamp *float64
RemoteRamp *float64
// Coalesce shares one in-flight execution across same-key callers; nil means true.
Coalesce *bool
// StaleOnErrorMaxAge is the exclusive age ceiling for serving a retained
// remote value after an eligible source error. It must exceed RemoteTTL.
// Nil omits recovery; an explicit zero disables an inherited policy.
StaleOnErrorMaxAge *time.Duration
// RemoteReadTimeout overrides the instance remote read deadline.
RemoteReadTimeout *time.Duration
Shadow *ShadowPolicy
}
Policy is an operation's static policy. Zero TTLs omit a layer; positive
TTLs are whole seconds. Pointer leaves distinguish omitted settings,
which inherit defaults and runtime overlays, from explicit zero or false.
func ParsePolicy(config any) (Policy, error)
ParsePolicy accepts the static JSON-shaped TypeScript configuration.
Explicit null leaves remain invalid; nil/Absent for the whole configuration
means none.
func SnapshotPolicy(p Policy) Policy
SnapshotPolicy detaches every optional leaf from mutable caller-owned
memory.
type PolicyDefaults struct{ RemoteReadTimeout time.Duration }
type PolicyOverlay struct {
RequestLocal *bool
LocalTTL *time.Duration
RemoteTTL *time.Duration
LocalRamp *float64
RemoteRamp *float64
Coalesce *bool
StaleOnErrorMaxAge *time.Duration
RemoteReadTimeout *time.Duration
Shadow *ShadowPolicy
}
PolicyOverlay is a typed sparse overlay. Nil leaves inherit. Durations must
be whole seconds for TTLs and recovery ages and whole milliseconds for the
read timeout; other values are treated as invalid leaves with the same
narrow consequences as an invalid JSON leaf.
type PolicyProvider func(context.Context, Identity) (RuntimePolicy, error)
PolicyProvider returns a sparse runtime overlay for one invocation. A nil
overlay inherits the static policy; an error bypasses caching for the call.
type PreciseClock interface {
ElapsedTime() time.Duration
}
PreciseClock optionally preserves fractional milliseconds for deadlines
and diagnostics. Local TTL uses whole milliseconds from Clock.ElapsedMS.
ElapsedTime and ElapsedMS must use the same monotonic origin. Existing
integer clocks remain supported through Clock.ElapsedMS.
type ProcessCoalescingState struct {
ActiveLeaders int
ActiveFollowers int
// OldestLeaderAge is zero when no leader is active.
OldestLeaderAge time.Duration
}
ProcessCoalescingState reports the process-scoped single-flight table.
type PrometheusCollectorBinding struct {
Schema PrometheusCollectorSchema
Collector prometheus.Collector
}
PrometheusCollectorBinding makes an existing collector's schema explicit.
Collector must be an individually registered CounterVec or HistogramVec.
Schema is the caller's assertion about its construction options, including
histogram buckets: client_golang does not expose those options for an empty
HistogramVec. The adapter checks the declared schema and public descriptor
before reuse, without creating a temporary metric series.
type PrometheusCollectorSchema struct {
Kind, Name, Help string
Labels []string
Buckets []float64
}
PrometheusCollectorSchema fixes the TypeScript adapter wire contract.
func PrometheusCollectorSchemas(prefix string) []PrometheusCollectorSchema
type PrometheusMetrics struct {
// Has unexported fields.
}
func NewPrometheusMetrics(registry *prometheus.Registry, prefix string) (*PrometheusMetrics, error)
NewPrometheusMetrics creates collectors or reuses an earlier DialCache
group. Use NewPrometheusMetricsWithBindings to reuse externally created
collectors.
func NewPrometheusMetricsWithBindings(registry *prometheus.Registry, prefix string, bindings []PrometheusCollectorBinding) (adapter *PrometheusMetrics, err error)
NewPrometheusMetricsWithBindings validates every supplied binding before
atomically registering the remaining collectors. Previously observed values
remain on the same collector objects. As with registry configuration itself,
callers must not concurrently unregister/reconfigure the supplied collectors
during construction; concurrent observations remain safe.
func (adapter *PrometheusMetrics) ObserveEvent(event Event) error
type ReadResult struct {
Kind string
Reason string
ObservedWatermarkMS *uint64
Frame Frame
// RawSet marks an untrusted semantic adapter result, including explicit nil.
Raw any
RawSet bool
}
func DecodeFrame(raw []byte, tracked bool, watermark *string) ReadResult
DecodeFrame implements the protocol's classification precedence. A nil raw
value is absent; a present zero-length value is an unclassified miss.
func NormalizeReadResult(result ReadResult, tracked bool) ReadResult
NormalizeReadResult is the core trust boundary, above wire decoding. Miss
reason and refill fence are validated independently. Frame-shaped objects
ignore stray miss metadata; only kind:"miss" selects the miss branch.
func RawReadResult(value any) ReadResult
func (r ReadResult) Error() error
type RecoveryPredicate func(error) (bool, error)
RecoveryPredicate decides whether one source error may serve a retained
stale value. A returned error or panic denies recovery.
type RedisAdapter struct {
// Has unexported fields.
}
RedisAdapter borrows a connected, caller-owned go-redis standalone,
Sentinel, or Cluster client. It never connects/closes the client or changes
its options. Set finite client dial/read/write/retry budgets. Cancellation
after dispatch cannot prove a mutation did not execute; the cache bounds its
own wait.
func NewRedisAdapter(client redis.UniversalClient) *RedisAdapter
func (adapter *RedisAdapter) Invalidate(ctx context.Context, key string, invalidatedAtMS, futureMS int64) error
Invalidate keeps the caller's application-clock timestamp stable throughout
one logical dispatch. EVALSHA failure gets one EVAL retry; accepted but
invalid replies are errors and are never retried. The monotonic script is
idempotent even if the first command executed before its response was lost.
func (adapter *RedisAdapter) InvalidateDecimal(ctx context.Context, key, futureMS, invalidatedAtMS string) error
InvalidateDecimal exposes the script's raw decimal boundary for out-of-band
tooling and conformance replay. Validation inside Lua precedes every
mutation.
func (adapter *RedisAdapter) Read(ctx context.Context, valueKey, watermarkKey string) (ReadResult, error)
func (adapter *RedisAdapter) Write(ctx context.Context, key string, frame Frame, ttl time.Duration) error
Write performs exactly one native SET of the complete frame. It neither
reads nor modifies the entity watermark. A provided timestamp is exact.
func (adapter *RedisAdapter) WriteMilliseconds(ctx context.Context, key string, frame Frame, ttlMS float64) error
type RedisPayloadError struct{ Message string }
func (e *RedisPayloadError) Error() string
type RedisProtocolError struct{ Message string }
func (e *RedisProtocolError) Error() string
type Remote interface {
// Read returns the value at valueKey and, for a tracked read, the watermark
// at watermarkKey from one atomic primary snapshot.
Read(ctx context.Context, valueKey, watermarkKey string) (ReadResult, error)
// Write stores one complete frame with the given TTL in a single native SET.
Write(ctx context.Context, key string, frame Frame, ttl time.Duration) error
// Invalidate raises the watermark to the invalidation timestamp plus the
// future buffer. Both arguments are wire milliseconds.
Invalidate(ctx context.Context, watermarkKey string, invalidatedAtMS, futureBufferMS int64) error
}
Remote supplies atomic primary snapshots and complete, client-stamped
writes. Cancellation requests do not assert that a pending command has
stopped.
type RemoteReadTimeoutError struct{ Timeout time.Duration }
func (e *RemoteReadTimeoutError) Error() string
type ResolvedLayer struct {
Enabled bool
Reason string
Configured bool // valid TTL and ramp remain available when ramp excludes the key
TTL time.Duration
Ramp float64
}
type ResolvedPolicy struct {
RequestLocal bool
Coalesce bool
Local ResolvedLayer
Remote ResolvedLayer
RemoteReadTimeout time.Duration
StaleOnErrorMaxAge time.Duration
StaleOnErrorConfigError bool
Shadow ResolvedShadow
}
func ResolvePolicy(base Policy, overlay RuntimePolicy, identity Identity, defaults PolicyDefaults) (ResolvedPolicy, error)
ResolvePolicy merges sparse leaves once. A malformed container, boolean or
read deadline is an invocation-wide error; TTL/ramp errors disable only that
layer, while an invalid recovery option preserves valid remote serving.
type ResolvedShadow struct {
Enabled bool // cohort selection only; admission still needs an eligible path and hook
Ramp float64
// LogValue and LogDiff are the effective mismatch-logging leaves: each
// layer's LogMismatches expands first, then the leaves merge, and an
// invalid leaf acts off.
LogValue bool
LogDiff MismatchDiffLevel
ConfigError bool
// LoggingConfigError covers every invalid logging leaf and shorthand; record
// it once, only if a job is admitted, as in TypeScript.
LoggingConfigError bool
}
type RuntimePolicy interface {
// Has unexported methods.
}
RuntimePolicy is a sparse overlay applied over an operation's static policy:
either a typed *PolicyOverlay or a JSONPolicy in the configuration shape
shared with TypeScript.
func RawPolicy(value any) RuntimePolicy
RawPolicy wraps an arbitrary decoded JSON value as a runtime overlay so a
configuration service's reply can pass through unchanged. A value that is
not an object is an invocation-wide policy error, as in TypeScript.
type ShadowPolicy struct {
// Ramp is the shadow cohort percentage; nil and zero disable shadow work.
Ramp *float64
// LogMismatches is shorthand for the whole MismatchLogging group: true
// stands for Value true and Diff MismatchDiffValues, false for both off.
// Leaves set in this policy's MismatchLogging override what it expands to
// before a runtime overlay merges.
LogMismatches *bool
// MismatchLogging selects the content of the one bounded warning emitted
// per confirmed mismatch. Omitted leaves default off.
MismatchLogging *MismatchLoggingPolicy
}
ShadowPolicy configures detached remote shadow validation.
type Timer interface{ Stop() bool }
type TimerClock interface {
AfterFunc(delayMS int64, callback func()) Timer
}
TimerClock lets applications supply the timer source corresponding to Clock.
Callbacks must run at most once; Stop prevents a callback which has not
begun.