using System.Diagnostics.CodeAnalysis; using ZB.MOM.WW.MxGateway.Contracts.Proto; namespace ZB.MOM.WW.MxGateway.Server.Sessions; public interface ISessionManager { /// Opens a new gateway session and launches a worker process. /// Request payload. /// Client identity string. /// API key identifier of the caller creating the session. /// Token to cancel the asynchronous operation. /// The newly opened session. Task OpenSessionAsync( SessionOpenRequest request, string? clientIdentity, string? ownerKeyId, CancellationToken cancellationToken); /// /// Opens a new gateway session, stamping the owning API key's dashboard event-visibility /// tags onto it. /// /// Request payload. /// Client identity string. /// API key identifier of the caller creating the session. /// /// The owner key's ApiKeyConstraints.DashboardTags. Null or empty opens an untagged /// session. Never sourced from the client's wire request — see /// docs/plans/2026-07-10-dashboard-session-acl-tst15.md §3.1. /// /// Token to cancel the asynchronous operation. /// The newly opened session. /// /// The default implementation forwards to the tagless overload, so an implementation that /// does not model tags (unit-test fakes) opens an untagged session. That is the /// fail-closed direction: untagged sessions are the least dashboard-visible ones. /// Task OpenSessionAsync( SessionOpenRequest request, string? clientIdentity, string? ownerKeyId, IReadOnlyList? ownerDashboardTags, CancellationToken cancellationToken) => OpenSessionAsync(request, clientIdentity, ownerKeyId, cancellationToken); /// Attempts to retrieve a session by ID. /// Identifier of the session. /// The retrieved session, if found. /// True if the session exists; otherwise false. bool TryGetSession( string sessionId, [MaybeNullWhen(false)] out GatewaySession session); /// Invokes a command on the worker for the specified session. /// Identifier of the session. /// Command to invoke. /// Token to cancel the asynchronous operation. /// The command reply from the worker. Task InvokeAsync( string sessionId, WorkerCommand command, CancellationToken cancellationToken); /// Closes a session and terminates its worker process. /// Identifier of the session to close. /// Token to cancel the asynchronous operation. /// The result of closing the session. Task CloseSessionAsync( string sessionId, CancellationToken cancellationToken); /// /// Forcefully terminates a session's worker without attempting graceful shutdown, /// transitions the session to Closed, and removes it from the registry. /// /// Identifier of the session whose worker to kill. /// Reason for killing the worker (recorded in logs/audit). /// Token to cancel the asynchronous operation. /// The result of closing the session. Task KillWorkerAsync( string sessionId, string reason, CancellationToken cancellationToken); /// Closes all sessions with expired leases at the specified time. /// The current time to evaluate expiration against. /// Token to cancel the asynchronous operation. /// The number of sessions closed. /// /// A close that fails does not abandon the rest of the pass: every session selected by this /// sweep is attempted, and the first failure is then rethrown so the caller still observes /// (and logs) that the sweep failed. Which failure surfaces is nondeterministic when several /// closes fail in the same pass, because the closes run concurrently. /// Task CloseExpiredLeasesAsync( DateTimeOffset now, CancellationToken cancellationToken); /// Shuts down all sessions and the session manager. /// /// Token that degrades the drain rather than cancelling it. It is passed only to each /// session's graceful close; the drain loop and the kill fallback are not bound to it, so /// cancelling turns the drain into a kill sweep instead of abandoning the untried sessions as /// leaked workers. The call therefore overruns a cancelled token by a bounded amount — /// roughly ceil(sessionCount / 4) batches of the worker shutdown timeout in the worst /// case, where 4 is MaxParallelSessionCloses. /// /// A task that represents the asynchronous operation. Task ShutdownAsync(CancellationToken cancellationToken); }