feat(sessions): per-subscriber backpressure isolation in SessionEventDistributor

This commit is contained in:
Joseph Doherty
2026-06-15 13:39:25 -04:00
parent 61627fc5b0
commit 039111ca05
9 changed files with 308 additions and 66 deletions
@@ -30,13 +30,17 @@ public sealed class EventStreamService(
/// queue-depth metrics, and the backpressure/overflow policy.
/// </para>
/// <para>
/// Overflow detection: the distributor's per-subscriber channel is bounded and the
/// pump drops (does not block) on a full channel. Worker sequences are contiguous
/// and the pump preserves order, so a gap between consecutive delivered
/// <see cref="MxEvent.WorkerSequence"/> values means the pump dropped events for
/// this slow subscriber — that is the overflow signal that, before Task 4, was a
/// full per-RPC channel. The FailFast / DisconnectSubscriber semantics are
/// unchanged. Task 5 takes over the per-subscriber isolation policy.
/// Overflow handling (Task 5): the distributor's per-subscriber channel is bounded
/// and the pump writes non-blocking. When this subscriber's channel is full the pump
/// applies the per-subscriber backpressure policy and completes this subscriber's
/// channel with a <see cref="SessionManagerException"/>
/// (<see cref="SessionManagerErrorCode.EventQueueOverflow"/>). That terminal fault
/// surfaces here when the reader's <c>MoveNextAsync</c> throws, and — like the
/// pre-epic per-RPC overflow — it propagates to the gRPC client unchanged. The
/// overflow metric, and (in the legacy single-subscriber FailFast case) the session
/// fault + fault metric, are recorded by the distributor's overflow handler so the
/// session, the pump, and other subscribers are isolated from this subscriber's
/// slowness.
/// </para>
/// </remarks>
/// <param name="request">Stream events request.</param>