Add XML documentation across gateway, worker, and .NET client

This commit is contained in:
Joseph Doherty
2026-04-30 11:49:58 -04:00
parent 4731ab535c
commit eed1e88a37
269 changed files with 4555 additions and 13 deletions
@@ -15,6 +15,20 @@ public sealed class GatewaySession
private bool _closeStarted;
private int _activeEventSubscriberCount;
/// <summary>
/// Initializes a gateway session with session metadata and timeout configuration.
/// </summary>
/// <param name="sessionId">Identifier of the session.</param>
/// <param name="backendName">Name of the backend MXAccess proxy server.</param>
/// <param name="pipeName">Name of the named pipe for gateway-worker IPC.</param>
/// <param name="nonce">Security nonce for worker validation.</param>
/// <param name="clientIdentity">Client identity from the authentication context.</param>
/// <param name="clientSessionName">Client-supplied session name.</param>
/// <param name="clientCorrelationId">Client-supplied correlation identifier.</param>
/// <param name="commandTimeout">Timeout for command invocation.</param>
/// <param name="startupTimeout">Timeout for worker process startup.</param>
/// <param name="shutdownTimeout">Timeout for worker process shutdown.</param>
/// <param name="openedAt">Timestamp when the session opened.</param>
public GatewaySession(
string sessionId,
string backendName,
@@ -62,32 +76,74 @@ public sealed class GatewaySession
_lastClientActivityAt = openedAt;
}
/// <summary>
/// Gets the session identifier.
/// </summary>
public string SessionId { get; }
/// <summary>
/// Gets the backend MXAccess proxy server name.
/// </summary>
public string BackendName { get; }
/// <summary>
/// Gets the named pipe name for gateway-worker IPC.
/// </summary>
public string PipeName { get; }
/// <summary>
/// Gets the security nonce for worker validation.
/// </summary>
public string Nonce { get; }
/// <summary>
/// Gets the client identity from the authentication context.
/// </summary>
public string? ClientIdentity { get; }
/// <summary>
/// Gets the client-supplied session name.
/// </summary>
public string? ClientSessionName { get; }
/// <summary>
/// Gets the client-supplied correlation identifier.
/// </summary>
public string? ClientCorrelationId { get; }
/// <summary>
/// Gets the command invocation timeout.
/// </summary>
public TimeSpan CommandTimeout { get; }
/// <summary>
/// Gets the worker process startup timeout.
/// </summary>
public TimeSpan StartupTimeout { get; }
/// <summary>
/// Gets the worker process shutdown timeout.
/// </summary>
public TimeSpan ShutdownTimeout { get; }
/// <summary>
/// Gets the timestamp when the session opened.
/// </summary>
public DateTimeOffset OpenedAt { get; }
/// <summary>
/// Gets the worker process identifier, or null if not yet attached.
/// </summary>
public int? WorkerProcessId => _workerClient?.ProcessId;
/// <summary>
/// Gets the attached worker client, or null if not yet attached.
/// </summary>
public IWorkerClient? WorkerClient => _workerClient;
/// <summary>
/// Gets the current session state.
/// </summary>
public SessionState State
{
get
@@ -99,6 +155,9 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Gets the timestamp of the most recent client activity.
/// </summary>
public DateTimeOffset LastClientActivityAt
{
get
@@ -110,6 +169,9 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Gets the lease expiration timestamp, or null if no lease is active.
/// </summary>
public DateTimeOffset? LeaseExpiresAt
{
get
@@ -121,6 +183,9 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Gets the fault description if the session is faulted, or null.
/// </summary>
public string? FinalFault
{
get
@@ -132,6 +197,9 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Gets the count of active event stream subscribers.
/// </summary>
public int ActiveEventSubscriberCount
{
get
@@ -143,6 +211,10 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Attaches the worker client for this session.
/// </summary>
/// <param name="workerClient">Worker client to attach.</param>
public void AttachWorkerClient(IWorkerClient workerClient)
{
ArgumentNullException.ThrowIfNull(workerClient);
@@ -153,6 +225,10 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Transitions the session to a new state with constraints for terminal states.
/// </summary>
/// <param name="nextState">Next session state to transition to.</param>
public void TransitionTo(SessionState nextState)
{
lock (_syncRoot)
@@ -171,11 +247,18 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Transitions the session to the Ready state.
/// </summary>
public void MarkReady()
{
TransitionTo(SessionState.Ready);
}
/// <summary>
/// Transitions the session to the Faulted state with a fault description.
/// </summary>
/// <param name="reason">Reason for the fault.</param>
public void MarkFaulted(string reason)
{
lock (_syncRoot)
@@ -190,6 +273,10 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Updates the timestamp of the most recent client activity.
/// </summary>
/// <param name="activityAt">Timestamp of the client activity.</param>
public void TouchClientActivity(DateTimeOffset activityAt)
{
lock (_syncRoot)
@@ -198,6 +285,10 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Extends the session lease to the specified expiration time.
/// </summary>
/// <param name="leaseExpiresAt">Timestamp when the lease expires.</param>
public void ExtendLease(DateTimeOffset leaseExpiresAt)
{
lock (_syncRoot)
@@ -206,6 +297,10 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Determines whether the session lease has expired.
/// </summary>
/// <param name="now">Current timestamp for comparison.</param>
public bool IsLeaseExpired(DateTimeOffset now)
{
lock (_syncRoot)
@@ -214,6 +309,10 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Attaches an event subscriber and returns a disposable lease.
/// </summary>
/// <param name="allowMultipleSubscribers">If true, allows multiple concurrent event subscribers.</param>
public IDisposable AttachEventSubscriber(bool allowMultipleSubscribers)
{
lock (_syncRoot)
@@ -237,6 +336,11 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Invokes a worker command synchronously and returns the reply.
/// </summary>
/// <param name="command">Worker command to invoke.</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
public async Task<WorkerCommandReply> InvokeAsync(
WorkerCommand command,
CancellationToken cancellationToken)
@@ -247,6 +351,12 @@ public sealed class GatewaySession
return await workerClient.InvokeAsync(command, CommandTimeout, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Executes a bulk add-item command for the specified server and tag addresses.
/// </summary>
/// <param name="serverHandle">Server handle returned by the worker.</param>
/// <param name="tagAddresses">Tag addresses to add.</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
public Task<IReadOnlyList<SubscribeResult>> AddItemBulkAsync(
int serverHandle,
IReadOnlyList<string> tagAddresses,
@@ -266,6 +376,12 @@ public sealed class GatewaySession
cancellationToken);
}
/// <summary>
/// Executes a bulk advise-item command for the specified server and item handles.
/// </summary>
/// <param name="serverHandle">Server handle returned by the worker.</param>
/// <param name="itemHandles">Item handles to advise.</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
public Task<IReadOnlyList<SubscribeResult>> AdviseItemBulkAsync(
int serverHandle,
IReadOnlyList<int> itemHandles,
@@ -285,6 +401,12 @@ public sealed class GatewaySession
cancellationToken);
}
/// <summary>
/// Executes a bulk remove-item command for the specified server and item handles.
/// </summary>
/// <param name="serverHandle">Server handle returned by the worker.</param>
/// <param name="itemHandles">Item handles to remove.</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
public Task<IReadOnlyList<SubscribeResult>> RemoveItemBulkAsync(
int serverHandle,
IReadOnlyList<int> itemHandles,
@@ -304,6 +426,12 @@ public sealed class GatewaySession
cancellationToken);
}
/// <summary>
/// Executes a bulk un-advise-item command for the specified server and item handles.
/// </summary>
/// <param name="serverHandle">Server handle returned by the worker.</param>
/// <param name="itemHandles">Item handles to un-advise.</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
public Task<IReadOnlyList<SubscribeResult>> UnAdviseItemBulkAsync(
int serverHandle,
IReadOnlyList<int> itemHandles,
@@ -323,6 +451,12 @@ public sealed class GatewaySession
cancellationToken);
}
/// <summary>
/// Executes a bulk subscribe command for the specified server and tag addresses.
/// </summary>
/// <param name="serverHandle">Server handle returned by the worker.</param>
/// <param name="tagAddresses">Tag addresses to subscribe to.</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
public Task<IReadOnlyList<SubscribeResult>> SubscribeBulkAsync(
int serverHandle,
IReadOnlyList<string> tagAddresses,
@@ -342,6 +476,12 @@ public sealed class GatewaySession
cancellationToken);
}
/// <summary>
/// Executes a bulk unsubscribe command for the specified server and item handles.
/// </summary>
/// <param name="serverHandle">Server handle returned by the worker.</param>
/// <param name="itemHandles">Item handles to unsubscribe from.</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
public Task<IReadOnlyList<SubscribeResult>> UnsubscribeBulkAsync(
int serverHandle,
IReadOnlyList<int> itemHandles,
@@ -361,6 +501,10 @@ public sealed class GatewaySession
cancellationToken);
}
/// <summary>
/// Reads events from the worker as an asynchronous enumerable stream.
/// </summary>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
public IAsyncEnumerable<WorkerEvent> ReadEventsAsync(CancellationToken cancellationToken)
{
IWorkerClient workerClient = GetReadyWorkerClient();
@@ -369,6 +513,11 @@ public sealed class GatewaySession
return workerClient.ReadEventsAsync(cancellationToken);
}
/// <summary>
/// Closes the session and shuts down the worker process.
/// </summary>
/// <param name="reason">Reason for closing the session.</param>
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
public async Task<SessionCloseResult> CloseAsync(
string reason,
CancellationToken cancellationToken)
@@ -426,12 +575,19 @@ public sealed class GatewaySession
}
}
/// <summary>
/// Terminates the worker process immediately.
/// </summary>
/// <param name="reason">Reason for killing the worker.</param>
public void KillWorker(string reason)
{
_workerClient?.Kill(reason);
TransitionTo(SessionState.Closed);
}
/// <summary>
/// Disposes the session and frees associated resources.
/// </summary>
public async ValueTask DisposeAsync()
{
_closeLock.Dispose();
@@ -500,6 +656,9 @@ public sealed class GatewaySession
{
private bool _disposed;
/// <summary>
/// Disposes the lease and detaches the event subscriber.
/// </summary>
public void Dispose()
{
if (_disposed)