f40409a688
Tracking IDs are review bookkeeping that rots in shipped source; the rationale they tagged is kept. Comment-only change (CommentChecker 458 -> 16 false positives).
112 lines
5.8 KiB
C#
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);
|
|
}
|