Files
mxaccessgw/src/ZB.MOM.WW.MxGateway.Server/Sessions/ISessionManager.cs
T
Joseph Doherty f40409a688
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (push) Successful in 1m16s
ci / java (push) Successful in 2m5s
ci / portable (push) Failing after 5m9s
docs: strip task-tracking IDs from code comments and fill missing XML docs
Tracking IDs are review bookkeeping that rots in shipped source; the rationale they tagged is kept. Comment-only change (CommentChecker 458 -> 16 false positives).
2026-10-07 15:34:32 -04:00

112 lines
5.8 KiB
C#

using System.Diagnostics.CodeAnalysis;
using ZB.MOM.WW.MxGateway.Contracts.Proto;
namespace ZB.MOM.WW.MxGateway.Server.Sessions;
public interface ISessionManager
{
/// <summary>Opens a new gateway session and launches a worker process.</summary>
/// <param name="request">Request payload.</param>
/// <param name="clientIdentity">Client identity string.</param>
/// <param name="ownerKeyId">API key identifier of the caller creating the session.</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
/// <returns>The newly opened session.</returns>
Task<GatewaySession> OpenSessionAsync(
SessionOpenRequest request,
string? clientIdentity,
string? ownerKeyId,
CancellationToken cancellationToken);
/// <summary>
/// Opens a new gateway session, stamping the owning API key's dashboard event-visibility
/// tags onto it.
/// </summary>
/// <param name="request">Request payload.</param>
/// <param name="clientIdentity">Client identity string.</param>
/// <param name="ownerKeyId">API key identifier of the caller creating the session.</param>
/// <param name="ownerDashboardTags">
/// The owner key's <c>ApiKeyConstraints.DashboardTags</c>. Null or empty opens an untagged
/// session. Never sourced from the client's wire request — see
/// <c>docs/plans/2026-07-10-dashboard-session-acl-tst15.md</c> §3.1.
/// </param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
/// <returns>The newly opened session.</returns>
/// <remarks>
/// The default implementation forwards to the tagless overload, so an implementation that
/// does not model tags (unit-test fakes) opens an <em>untagged</em> session. That is the
/// fail-closed direction: untagged sessions are the least dashboard-visible ones.
/// </remarks>
Task<GatewaySession> OpenSessionAsync(
SessionOpenRequest request,
string? clientIdentity,
string? ownerKeyId,
IReadOnlyList<string>? ownerDashboardTags,
CancellationToken cancellationToken)
=> OpenSessionAsync(request, clientIdentity, ownerKeyId, cancellationToken);
/// <summary>Attempts to retrieve a session by ID.</summary>
/// <param name="sessionId">Identifier of the session.</param>
/// <param name="session">The retrieved session, if found.</param>
/// <returns>True if the session exists; otherwise false.</returns>
bool TryGetSession(
string sessionId,
[MaybeNullWhen(false)] out GatewaySession session);
/// <summary>Invokes a command on the worker for the specified session.</summary>
/// <param name="sessionId">Identifier of the session.</param>
/// <param name="command">Command to invoke.</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
/// <returns>The command reply from the worker.</returns>
Task<WorkerCommandReply> InvokeAsync(
string sessionId,
WorkerCommand command,
CancellationToken cancellationToken);
/// <summary>Closes a session and terminates its worker process.</summary>
/// <param name="sessionId">Identifier of the session to close.</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
/// <returns>The result of closing the session.</returns>
Task<SessionCloseResult> CloseSessionAsync(
string sessionId,
CancellationToken cancellationToken);
/// <summary>
/// Forcefully terminates a session's worker without attempting graceful shutdown,
/// transitions the session to Closed, and removes it from the registry.
/// </summary>
/// <param name="sessionId">Identifier of the session whose worker to kill.</param>
/// <param name="reason">Reason for killing the worker (recorded in logs/audit).</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
/// <returns>The result of closing the session.</returns>
Task<SessionCloseResult> KillWorkerAsync(
string sessionId,
string reason,
CancellationToken cancellationToken);
/// <summary>Closes all sessions with expired leases at the specified time.</summary>
/// <param name="now">The current time to evaluate expiration against.</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
/// <returns>The number of sessions closed.</returns>
/// <remarks>
/// 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.
/// </remarks>
Task<int> CloseExpiredLeasesAsync(
DateTimeOffset now,
CancellationToken cancellationToken);
/// <summary>Shuts down all sessions and the session manager.</summary>
/// <param name="cancellationToken">
/// Token that <em>degrades</em> 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 <c>ceil(sessionCount / 4)</c> batches of the worker shutdown timeout in the worst
/// case, where 4 is <c>MaxParallelSessionCloses</c>.
/// </param>
/// <returns>A task that represents the asynchronous operation.</returns>
Task ShutdownAsync(CancellationToken cancellationToken);
}