SpeechRelay Docs

Resume

Reattach a dropped client to the same worker instance and receive the events it missed — off by default.

Reattach and replay

When the worker has resume enabled (DICON_SESSION_RESUME; off by default), a client whose transport dropped may reattach to the same worker instance and receive the events it missed:

  1. Reconnect to /v1/sessions/{session_id}/stream?last_seq=N with subprotocol dicon.v1, where N is the last seq the client processed. The handshake requires the same Authorization header as any fresh connection — a session id is a public identifier, never a bearer token.
  2. The server replays every retained event with seq strictly greater than N, in order, with no duplicates and no gaps, then sends one session.resumed event carrying replayed_events, then live events. seq remains monotonically increasing across the whole session.
  3. Retention is a bounded ring: the last DICON_RESUME_BUFFER_EVENTS events per session. If an event after N is no longer retained, or N is beyond the newest event, the server refuses explicitly: it sends an error event saying so and closes with code 4410. It never replays a partial history; the client must start a new session.

Grace window

A detached session survives at most DICON_RESUME_GRACE_SECONDS (DICON_IDLE_TIMEOUT_SECONDS may end it sooner) and is cancelled exactly as today if nobody reattaches.

Refusal close codes

Resume refusals accept the socket first, deliver one error event, then close, because a rejection before accept() collapses into a bare HTTP response that discards codes and reasons:

Old clients

An old client that never presents last_seq is unaffected either way: plain reconnects keep the existing claim-or-4409 behaviour, without replay.

Cross-instance resume does not exist

A reattach reaches only the worker holding the session in memory. Instance replacement still drops every stream. While enabled, a detached session keeps holding its worker slot for the grace window — this capacity cost is why the feature ships disabled.