fix(communication): release the _activeStreams slot when relay ActorOf throws (review 2026-10-21 03/M-2)

This commit is contained in:
Joseph Doherty
2026-10-22 06:13:43 -04:00
parent dd60e236bd
commit 15496575bc
2 changed files with 44 additions and 3 deletions
@@ -478,6 +478,29 @@ public class SiteStreamGrpcServerTests : TestKit
subscriber.DidNotReceive().RemoveSubscriber(Arg.Any<IActorRef>());
}
/// <summary>
/// Review 2026-10-21 03/M-2: if <c>ActorOf</c> throws (the actor system terminating via
/// the downed-node watchdog, so <c>_shuttingDown</c> was never set), the
/// <c>_activeStreams</c> slot registered just before it must not leak.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ActorOfThrows_DoesNotLeakActiveStreamSlot()
{
var terminated = ActorSystem.Create("m2-terminated");
await terminated.Terminate();
var server = CreateServer();
server.SetReady(terminated);
var writer = Substitute.For<IServerStreamWriter<SiteStreamEvent>>();
await Assert.ThrowsAnyAsync<Exception>(
() => server.SubscribeInstance(MakeRequest("corr-m2"), writer, CreateMockContext()));
Assert.Equal(0, server.ActiveStreamCount);
_subscriber.DidNotReceive().Subscribe(Arg.Any<string>(), Arg.Any<IActorRef>());
}
/// <summary>Verifies that the active subscribers gauge rises to one on connect and returns to zero on cancellation.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]