fix(sessions): make EventSubscriberLease dispose atomic; dedupe lease dispose
Issue 1: replace plain bool _disposed in EventSubscriberLease with an Interlocked.Exchange int (_leaseDisposed) matching the SubscriberLease pattern in SessionEventDistributor. Concurrent stream-completion + client-cancellation racing Dispose() now decrements _activeEventSubscriberCount exactly once, never to -1. Issue 5: remove the `using` declaration on the subscriber lease in EventStreamService.StreamEventsAsync; the finally block already disposes it alongside the reader, so the using was a redundant second dispose on the same code path. Issue 2: add an inline comment at the StartAsync().GetAwaiter().GetResult() call documenting the sync-over-async invariant (StartAsync only schedules via Task.Run and is synchronous; do not make it truly async without changing this call site). Issue 10: remove the redundant .WithCancellation(cancellationToken) chained on ReadEventsAsync(cancellationToken) in MapWorkerEventsAsync; the [EnumeratorCancellation] token already flows through the direct argument. Issue 9: add EventSubscriberLease_ConcurrentDispose_DecrementsCountExactlyOnce to GatewaySessionTests — 16 concurrent Dispose() calls on the same lease for 200 iterations; asserts count is exactly 0 after each race and a subsequent single-subscriber AttachEventSubscriber succeeds.
This commit is contained in:
@@ -53,7 +53,10 @@ public sealed class EventStreamService(
|
||||
$"Session {request.SessionId} was not found.");
|
||||
}
|
||||
|
||||
using IEventSubscriberLease subscriber = session.AttachEventSubscriber(
|
||||
// No `using` here — subscriber.Dispose() is called exactly once in the finally
|
||||
// block below, which also disposes the reader. A `using` declaration would add a
|
||||
// second Dispose on the same path and double-decrement the session subscriber count.
|
||||
IEventSubscriberLease subscriber = session.AttachEventSubscriber(
|
||||
options.Value.Sessions.AllowMultipleEventSubscribers);
|
||||
|
||||
int streamQueueDepth = 0;
|
||||
|
||||
Reference in New Issue
Block a user