Skip to content

docs: keep the event-bus loop short; a held event delays noticing a lost server #316

Closed

Description

@Blind-Striker

What

The streaming guide's "A live bus that reconnects" section (added by #315 for #176) should tell consumers to keep the await foreach loop over client.Events.SubscribeAsync short. Long work belongs elsewhere: hand each event to a Channel<IEvent> (or another queue) and return to the loop at once. The guide should include a short sample of that hand-off.

Why

The SDK's bus is pull-based. The next bytes are read only when the consumer asks for the next event. While the consumer holds an event, its 45 s idle window is stopped, because the consumer's own time is not the server's silence (client-runtime.md, Server-sent events).

The consequence is that a server lost while the consumer holds an event is noticed only when the consumer asks again:

  • Clean loss (process ended, connection reset): the next read fails at once, and the bus reconnects one second later. Detection is late by the time the event was held.
  • Half-open connection (no reset ever arrives): the idle window runs its full 45 s from the moment the consumer asks again.

Upstream's first-party client reads in the background, so it notices the loss and reconnects while its consumer is busy. The gap of missed events is therefore shorter there. Its consumers are UI handlers that never hold an event, so the question doesn't arise for them.

A consumer that keeps the loop short gets the same timing as upstream, with no change to the SDK. The guide should say so, and say why: a repeated EventServerConnected still means events were missed, and the shorter the loop, the smaller that gap.

Considered and not proposed

The SDK could read the bus in the background itself, through an internal buffer. That costs:

  • A new decision on the buffer. Unbounded, a slow consumer grows the client's memory. Bounded, the SDK has to choose what to do when it is full, which would be a new behaviour that upstream doesn't have.
  • The natural back-pressure. Today a slow consumer fills TCP, and the server fails the stream with its own slow-consumer failure frame, which the bus reconnects from.
  • A background task per stream, with failure routing and disposal ordering on top.

The maintainer (2026-10-15) chose to document the trade-off rather than change the model. An opt-in buffered subscription can be revisited if consumers ask for it.

Acceptance

  • docs/guide/streaming.md, in "A live bus that reconnects", gets:
    • one paragraph on keeping the loop short and what holding an event delays;
    • a minimal Channel hand-off sample, which compiles against the current public API.
  • docs/architecture/client-runtime.md needs no change. It already states that the window stops while an event is held.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions