feat(clients): CLI-15 surface ReplayGap reconnect sentinel as typed signal (4/5 clients)
The gateway emits a ReplayGap sentinel MxEvent at the head of a StreamEvents stream resumed via after_worker_sequence when the requested cursor predates the oldest retained event. Clients previously ignored it, silently mis-treating a lossy resume as continuous. Each client now surfaces the sentinel as a distinct, typed, non-terminal signal (never synthesized, never swallowed) so a consumer can detect the gap and re-snapshot; resume contract is after_worker_sequence = oldest_available_sequence - 1. - .NET: MxEventStreamItem (IsReplayGap/ReplayGap/Event) via new StreamEventItemsAsync + AsStreamItemsAsync extension. Build clean, 87 passed. - Go: EventResult.ReplayGap field + IsReplayGap(); ReplayGap type alias. build/vet/test clean. - Rust: EventItem enum (Event/ReplayGap); EventStream now yields Result<EventItem, Error>; CLI renders REPLAY_GAP line / replayGap JSON. fmt/check/test/clippy clean. - Python: ReplayGap dataclass; stream_events yields pb.MxEvent | ReplayGap. 131 passed. - Shared docs: ClientLibrariesDesign non-goals reframed (reconnect-replay protocol is consumable; auto-reconnect stays a non-goal); CrossLanguageSmokeMatrix resume-gap note. Java client is deferred to the windev batch (no local JRE); CLI-15 stays open until it lands. Claude-Session: https://claude.ai/code/session_01DMXXvNuPekkkrTEyPNxEkW
This commit is contained in:
@@ -30,6 +30,14 @@ Each client entry defines commands for the same required operation sequence:
|
||||
The optional `write` command is documented separately because writing changes
|
||||
provider state and should only run when the operator supplies a safe test value.
|
||||
|
||||
When `stream-events` is resumed with an `after_worker_sequence` cursor that
|
||||
predates the oldest event still in the gateway's replay ring, the gateway emits a
|
||||
single `ReplayGap` sentinel at the head of the stream. Every client surfaces this
|
||||
as a distinct, typed, non-terminal signal (see each client README); the resume
|
||||
contract is `after_worker_sequence = oldest_available_sequence - 1`. The default
|
||||
smoke sequence opens a fresh stream (no cursor) and does not exercise the gap
|
||||
path; a resume-with-gap fixture case is tracked separately (TST-24).
|
||||
|
||||
## Integration Gate
|
||||
|
||||
Cross-language smoke execution is opt-in. Runners should skip the matrix unless
|
||||
|
||||
Reference in New Issue
Block a user