This document summarizes the production-facing contract of the public
github.com/cntryl/fitz-go/v2/fitz package.
The Go client validates route shape for ergonomics: scheme, path segment count, empty segments, and wildcard placement allowed for the called method. It does not validate route existence, permissions, authorization, realm semantics, resource names, or auth claims, and it does not normalize route strings.
KV, Queue, Stream, Notice, RPC worker, and Schedule registrations accept exact
routes plus whole-segment * and ** patterns, including wildcard realms.
KV, Queue, and Stream patterns must be capable of matching three segments;
Schedule patterns must match four; Notice and RPC have flexible depth. The
broker permits 128 wildcard registrations per domain and session; exact
registrations do not consume that quota. Lease subscriptions are different:
they accept only an exact lease://realm/area/resource route.
Notifications always expose the exact concrete delivery route. Queue availability notifications additionally expose ready, delayed, and inflight message counts. Duplicate local registrations for the same original string share one wire registration and reconnect restores active registrations.
Queue reserves accept general whole-segment patterns capable of matching three
segments. Stream READ and SUBSCRIBE accept concrete resources, realm/area/*,
realm/*/*, or stream://**; Stream LAST is concrete-route only. Every returned
QueueItem and StreamReadItem exposes
the exact concrete matched route, and Stream event records expose it through
StreamRecord.Route. Route-less reserve/read/last responses are not supported. If
any item contains an invalid concrete route, the entire response fails closed;
the client never returns a partial reservation or read batch.
Queue enqueue preserves the immediate Enqueue call and exposes delayed
visibility through EnqueueWithOptions(..., WithQueueEnqueueDelaySeconds(n)).
Connect(ctx)is one-shot for the initial connection. Concurrent or repeated calls while connected return nil without creating a second transport.- Automatic reconnect is enabled by default after the first successful connect.
WithReconnect(false, ..., ...)disables it;maxAttempts=0means unlimited. - Heartbeat is enabled by default. WebSocket uses ping/pong; TCP uses socket keepalive and never fabricates Fitz protocol frames.
- Automatic retries are enabled by default for the narrow replay-safe set:
KV
Get/Scan, StreamRead/ReadPage/Peek/Metadata, LeaseQuery, and QueueEnqueueonly after an explicit retryable broker rejection. - The outbound request queue is bounded. When saturated, operations fail with
ErrRequestQueueFull. - Detached subscription callbacks use a separate bounded queue. Configure it
with
WithAsyncHandlerQueueCapacity(default1024) and configure executing callbacks independently withWithAsyncHandlerMaxConcurrency(default256). The receive loop never waits for queue space. - Every KV, Notice, Queue, Lease, Schedule, and Stream callback subscription
exposes
Completion() <-chan error. Explicit unsubscribe yieldsnil. Saturation yields*AsyncHandlerOverflowError, terminates that local registration, and attempts a best-effort wire unsubscribe when it was the final local registration. Queue/Stream polling iterators and Schedule push iterators surface the same terminal error throughIterator.Err(). - RPC workers retain their protocol-level backpressure response on saturation; they are not converted to subscription completion errors.
- Async-handler saturation increments
fitz.async_handlers.saturated; active and queued work are observable throughfitz.async_handlers.activeandfitz.async_handlers.queued. - Schedule backend unavailability and broker saturation use
ErrCodeScheduleBackendError(7010).IsRetryableclassifies that code as retryable subject to operation safety. It is distinct from cron and parse errors and is never mapped to malformed schedule input.
Stateful handles are bound to the connection that created them. QueueItem,
Lease, KVTx, and StreamSession handles from a previous connection fail
fast with ErrStaleHandle after reconnect or close.
Managed WithLease callbacks receive their immutable admission fencing epoch through
LeaseAuthorityFromContext. The snapshot is copied from the final successful ACQUIRE,
including a deferred queue grant, before application code starts. Renewal may rotate the
private live credential but never changes the callback snapshot. Fencing tokens are ordered
only for successive owners of the same lease route; external stores retain the greatest
accepted value and reject lower values. Lease and LeaseInfo continue to hide raw live
credentials, and QUERY is not used to recover admission authority.
NewWakeGate, ReserveWhenAvailable, ReadWhenCommitted, and
WaitForNotifications support Go-native consumer loops. Subscriptions are wake
signals only for queue and stream helpers; reserve/read calls remain
authoritative.
Fast local verification must pass without Docker:
go test ./...Broker-backed acceptance and conformance are opt-in:
docker compose up -d
go test -tags=integration ./test ./test/conformance/...