fix(signalr): scope stream materializer to per-session actor to prevent actor leak#192
Merged
Merged
Conversation
…nt actor leak
SignalR sessions were materializing Akka.Streams pipelines using the system-level
materializer (.Run(_system)), which created all stream stage actors as children of
the global StreamSupervisor-0. These actors accumulated over the daemon's lifetime
and were only torn down at full system shutdown, producing the large burst of
Flow-*-actorRefSource* actors visible in shutdown logs.
Introduces SignalRSessionActor, a per-session binding actor that mirrors the
SlackThreadBindingActor pattern: it creates Context.Materializer(namePrefix:"signalr")
scoped to its own context so all stream actors become its children and are
automatically stopped when the session ends.
- Add SignalRSessionActor with Initializing/Active state machine, scoped materializer,
pipeline reinitialization on stream termination, and clean PostStop disposal
- Add SignalRGatewayHostingExtensions to register the signalr-gateway parent actor
(GenericChildPerEntityParent) and SignalRGatewayActorKey for DI lookup
- Rewrite SessionRegistry to delegate pipeline lifecycle to the actor via Tell;
registry now tracks session existence only (no stream state)
- Wire WithSignalRGateway() into Program.cs Akka builder
- Rewrite SessionRegistryTests to cover registry coordination behavior using a
StubRequiredActor that returns ActorRefs.Nobody
After this change: /netclaw/user/signalr-gateway/{sessionId} actors own their
streams; stopping the actor cleans up all stream children immediately.
62c192c to
56c6523
Compare
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SessionRegistry.MaterializeAndBindSessionAsync()called.Run(_system)for all stream materializations, creating stream stage actors under the globalStreamSupervisor-0. These accumulated over the daemon's lifetime and were only torn down at full system shutdown — visible as a large burst ofFlow-*-actorRefSource*actors in shutdown logs.SignalRSessionActor, a per-session binding actor mirroring theSlackThreadBindingActorpattern. Each actor createsContext.Materializer(namePrefix:"signalr")scoped to its own context, making all stream actors its children. When the session ends, the actor stops → materializer disposes → all stream children are automatically cleaned up./netclaw/user/signalr-gateway/{sessionId}(owned, lifecycle-bound streams) replaces orphaned actors underStreamSupervisor-0.Changes
SignalRSessionActor— per-session binding actor withInitializing/Activestate machine, scoped materializer, pipeline reinitialization on stream termination, andPostStopcleanupSignalRGatewayHostingExtensions— registerssignalr-gateway(GenericChildPerEntityParent) andSignalRGatewayActorKeySessionRegistry— rewritten to delegate pipeline lifecycle to the actor viaTell; now tracks session existence only (no stream state)Program.cs— wires.WithSignalRGateway()into the Akka builderSessionRegistryTests— rewritten to cover registry coordination behavior using aStubRequiredActorTest plan
dotnet test)dotnet slopwatch analyze— no new violationsFlow-*-actorRefSource*burst underStreamSupervisor-0/netclaw/user/signalr-gateway/and stop when sessions end