fix(sessions): refuse OpenSession while the gateway is stopping; drain until the registry is empty

ShutdownAsync iterated a single registry snapshot while Kestrel still
accepted OpenSession calls (ApplicationStopping fires before hosted
services stop), so a session opened behind the snapshot had nobody left to
close it and its x86 worker outlived the gateway as an orphan.

SessionManager now observes IHostApplicationLifetime.ApplicationStopping
(and sets the same flag at the start of ShutdownAsync) and rejects
OpenSessionAsync with the new SessionManagerErrorCode.GatewayStopping,
re-checked after registration so the flag write before the drain's
snapshot closes the race. GatewayStopping maps to gRPC Unavailable and is
not a fault. ShutdownAsync re-snapshots until the registry is empty,
bounded at three passes.
This commit is contained in:
Joseph Doherty
2026-10-22 06:23:40 -04:00
parent 09666cc719
commit 37ab629d70
6 changed files with 317 additions and 62 deletions
+2
View File
@@ -306,6 +306,8 @@ StatusCode statusCode = exception.ErrorCode switch
SessionManagerErrorCode.SessionLimitExceeded => StatusCode.ResourceExhausted,
SessionManagerErrorCode.OpenFailed => StatusCode.Unavailable,
SessionManagerErrorCode.CloseFailed => StatusCode.Unavailable,
SessionManagerErrorCode.PermissionDenied => StatusCode.PermissionDenied,
SessionManagerErrorCode.GatewayStopping => StatusCode.Unavailable,
_ => StatusCode.Unavailable,
};
```