From 3e339b2b7ab4dc0dc58c24c87de89cd5c6a67fe5 Mon Sep 17 00:00:00 2001
From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com>
Date: Tue, 23 Dec 2025 15:15:18 +0100
Subject: [PATCH] Add XML docs
---
...moteExec.Client.DependencyInjection.csproj | 1 +
...moteExecutorServiceCollectionExtensions.cs | 10 +++
RemoteExec.Client/AsyncManualResetEvent.cs | 18 +++++
.../Exceptions/MaxRetriesException.cs | 3 +
.../Exceptions/RemoteExecutionException.cs | 3 +
RemoteExec.Client/ILoadBalancingStrategy.cs | 8 ++
.../ResourceAwareStrategy.cs | 4 +
RemoteExec.Client/RemoteExec.Client.csproj | 1 +
RemoteExec.Client/RemoteExecLoggerProvider.cs | 13 ++++
.../RemoteExecutor.ConnectionManagement.cs | 8 ++
RemoteExec.Client/RemoteExecutor.cs | 77 +++++++++++++++++++
RemoteExec.Client/RemoteExecutorOptions.cs | 35 ++++++++-
RemoteExec.Client/ServerConnection.cs | 22 ++++++
.../ServerMetricsUpdatedEventArgs.cs | 10 +++
.../Configuration/ApiKeyConfiguration.cs | 15 ++++
.../AuthenticationConfiguration.cs | 6 ++
.../Controllers/AssemblyController.cs | 8 ++
RemoteExec.Server/Hubs/RemoteExecutionHub.cs | 33 ++++++++
.../ApiKeyAuthenticationMiddleware.cs | 13 ++++
.../RemoteJobAssemblyLoadContext.cs | 3 +
RemoteExec.Server/RequestAssemblyEventArgs.cs | 14 ++++
.../Services/MetricsBroadcastService.cs | 4 +
RemoteExec.Shared/RemoteExecutionRequest.cs | 22 ++++++
RemoteExec.Shared/RemoteExecutionResult.cs | 10 +++
RemoteExec.Shared/ServerMetrics.cs | 30 ++++++++
RemoteExec.Shared/TaskItem.cs | 10 +++
26 files changed, 377 insertions(+), 4 deletions(-)
diff --git a/RemoteExec.Client.DependencyInjection/RemoteExec.Client.DependencyInjection.csproj b/RemoteExec.Client.DependencyInjection/RemoteExec.Client.DependencyInjection.csproj
index 87def2e..1fc93c2 100644
--- a/RemoteExec.Client.DependencyInjection/RemoteExec.Client.DependencyInjection.csproj
+++ b/RemoteExec.Client.DependencyInjection/RemoteExec.Client.DependencyInjection.csproj
@@ -4,6 +4,7 @@
net10.0enableenable
+ True
diff --git a/RemoteExec.Client.DependencyInjection/RemoteExecutorServiceCollectionExtensions.cs b/RemoteExec.Client.DependencyInjection/RemoteExecutorServiceCollectionExtensions.cs
index 89dac4a..fe885b4 100644
--- a/RemoteExec.Client.DependencyInjection/RemoteExecutorServiceCollectionExtensions.cs
+++ b/RemoteExec.Client.DependencyInjection/RemoteExecutorServiceCollectionExtensions.cs
@@ -4,8 +4,18 @@ using Microsoft.Extensions.Logging;
namespace RemoteExec.Client.DependencyInjection;
+///
+/// Extension methods for registering RemoteExecutor with dependency injection.
+///
public static class RemoteExecutorServiceCollectionExtensions
{
+ ///
+ /// Adds a singleton RemoteExecutor to the service collection.
+ ///
+ /// The service collection to add to.
+ /// The URLs of the remote execution servers.
+ /// An optional action to configure the executor options.
+ /// The service collection for chaining.
public static IServiceCollection AddRemoteExecutor(this IServiceCollection services, string[] urls, Action? configure = null)
{
RemoteExecutorOptions options = new RemoteExecutorOptions();
diff --git a/RemoteExec.Client/AsyncManualResetEvent.cs b/RemoteExec.Client/AsyncManualResetEvent.cs
index aff7d68..ff6db55 100644
--- a/RemoteExec.Client/AsyncManualResetEvent.cs
+++ b/RemoteExec.Client/AsyncManualResetEvent.cs
@@ -1,9 +1,16 @@
namespace RemoteExec.Client;
+///
+/// An async-compatible manual reset event that can be awaited.
+///
internal class AsyncManualResetEvent
{
private volatile TaskCompletionSource _tcs = new(TaskCreationOptions.RunContinuationsAsynchronously);
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// If true, the event is initially signaled.
public AsyncManualResetEvent(bool initialState)
{
if (initialState)
@@ -12,16 +19,27 @@ internal class AsyncManualResetEvent
}
}
+ ///
+ /// Asynchronously waits for the event to be signaled.
+ ///
+ /// A cancellation token to cancel the wait operation.
+ /// A task that completes when the event is signaled.
public Task WaitAsync(CancellationToken ct)
{
return _tcs.Task.WaitAsync(ct);
}
+ ///
+ /// Sets the event to a signaled state, releasing all waiting tasks.
+ ///
public void Set()
{
_ = _tcs.TrySetResult(true);
}
+ ///
+ /// Resets the event to an unsignaled state.
+ ///
public void Reset()
{
while (true)
diff --git a/RemoteExec.Client/Exceptions/MaxRetriesException.cs b/RemoteExec.Client/Exceptions/MaxRetriesException.cs
index 4c96cce..ac73874 100644
--- a/RemoteExec.Client/Exceptions/MaxRetriesException.cs
+++ b/RemoteExec.Client/Exceptions/MaxRetriesException.cs
@@ -1,5 +1,8 @@
namespace RemoteExec.Client.Exceptions;
+///
+/// Exception thrown when a task exceeds the maximum number of retry attempts.
+///
public class MaxRetriesException(string message) : Exception(message)
{
}
diff --git a/RemoteExec.Client/Exceptions/RemoteExecutionException.cs b/RemoteExec.Client/Exceptions/RemoteExecutionException.cs
index c2fe637..7ecfdc5 100644
--- a/RemoteExec.Client/Exceptions/RemoteExecutionException.cs
+++ b/RemoteExec.Client/Exceptions/RemoteExecutionException.cs
@@ -1,5 +1,8 @@
namespace RemoteExec.Client.Exceptions;
+///
+/// Exception thrown when a remote method execution fails on the server.
+///
public class RemoteExecutionException(string message) : Exception(message)
{
}
\ No newline at end of file
diff --git a/RemoteExec.Client/ILoadBalancingStrategy.cs b/RemoteExec.Client/ILoadBalancingStrategy.cs
index 10cbc78..ee743f1 100644
--- a/RemoteExec.Client/ILoadBalancingStrategy.cs
+++ b/RemoteExec.Client/ILoadBalancingStrategy.cs
@@ -1,6 +1,14 @@
namespace RemoteExec.Client;
+///
+/// Defines a strategy for selecting a server from a pool of available servers for task distribution.
+///
public interface ILoadBalancingStrategy
{
+ ///
+ /// Selects the most appropriate server from the available servers based on the strategy's logic.
+ ///
+ /// The collection of available servers to choose from.
+ /// The selected server, or null if no suitable server is found.
ServerConnection? SelectServer(IEnumerable availableServers);
}
diff --git a/RemoteExec.Client/LoadBalancingStrategies/ResourceAwareStrategy.cs b/RemoteExec.Client/LoadBalancingStrategies/ResourceAwareStrategy.cs
index 2b3c08d..5e3f131 100644
--- a/RemoteExec.Client/LoadBalancingStrategies/ResourceAwareStrategy.cs
+++ b/RemoteExec.Client/LoadBalancingStrategies/ResourceAwareStrategy.cs
@@ -1,7 +1,11 @@
namespace RemoteExec.Client.LoadBalancingStrategies;
+///
+/// A load balancing strategy that selects servers based on CPU usage, active tasks, and backlog.
+///
internal class ResourceAwareStrategy : ILoadBalancingStrategy
{
+ ///
public ServerConnection? SelectServer(IEnumerable availableServers)
{
return availableServers.MinBy(s =>
diff --git a/RemoteExec.Client/RemoteExec.Client.csproj b/RemoteExec.Client/RemoteExec.Client.csproj
index 16bc780..c43c42c 100644
--- a/RemoteExec.Client/RemoteExec.Client.csproj
+++ b/RemoteExec.Client/RemoteExec.Client.csproj
@@ -4,6 +4,7 @@
net10.0enableenable
+ True
diff --git a/RemoteExec.Client/RemoteExecLoggerProvider.cs b/RemoteExec.Client/RemoteExecLoggerProvider.cs
index f8ae5f6..50eb7a3 100644
--- a/RemoteExec.Client/RemoteExecLoggerProvider.cs
+++ b/RemoteExec.Client/RemoteExecLoggerProvider.cs
@@ -2,21 +2,33 @@
namespace RemoteExec.Client;
+///
+/// Logger provider that forwards log messages to an existing logger instance.
+///
internal class RemoteExecLoggerProvider : ILoggerProvider
{
private bool disposedValue;
private readonly ILogger logger;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The logger instance to forward messages to.
public RemoteExecLoggerProvider(ILogger logger)
{
this.logger = logger;
}
+ ///
public ILogger CreateLogger(string categoryName)
{
return logger;
}
+ ///
+ /// Disposes the logger provider.
+ ///
+ /// True if disposing managed resources.
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
@@ -26,6 +38,7 @@ internal class RemoteExecLoggerProvider : ILoggerProvider
}
}
+ ///
public void Dispose()
{
Dispose(disposing: true);
diff --git a/RemoteExec.Client/RemoteExecutor.ConnectionManagement.cs b/RemoteExec.Client/RemoteExecutor.ConnectionManagement.cs
index 787c68a..9e4ac1d 100644
--- a/RemoteExec.Client/RemoteExecutor.ConnectionManagement.cs
+++ b/RemoteExec.Client/RemoteExecutor.ConnectionManagement.cs
@@ -10,6 +10,10 @@ namespace RemoteExec.Client;
public partial class RemoteExecutor
{
+ ///
+ /// Starts the remote executor, connecting to all configured servers and beginning task distribution.
+ ///
+ /// A cancellation token to cancel the operation.
public async Task StartAsync(CancellationToken cancellationToken = default)
{
// Dispose previous cancellation token source if exists
@@ -40,6 +44,10 @@ public partial class RemoteExecutor
distributorTask = Task.Run(() => DistributorLoop(distributorCts.Token), distributorCts.Token);
}
+ ///
+ /// Stops the remote executor, disconnecting from all servers and stopping task distribution.
+ ///
+ /// A cancellation token to cancel the operation.
public async Task StopAsync(CancellationToken cancellationToken = default)
{
logger.LogInformation("Stopping RemoteExecutor...");
diff --git a/RemoteExec.Client/RemoteExecutor.cs b/RemoteExec.Client/RemoteExecutor.cs
index 8a4631a..db4fafe 100644
--- a/RemoteExec.Client/RemoteExecutor.cs
+++ b/RemoteExec.Client/RemoteExecutor.cs
@@ -11,6 +11,9 @@ using System.Text.Json;
namespace RemoteExec.Client;
+///
+/// Manages remote execution of static methods across one or more server connections with load balancing and fault tolerance.
+///
public partial class RemoteExecutor : IAsyncDisposable
{
private readonly BlockingCollection globalQueue;
@@ -27,20 +30,45 @@ public partial class RemoteExecutor : IAsyncDisposable
private bool disposedValue;
+ ///
+ /// Occurs when server metrics are updated.
+ ///
public event EventHandler? MetricsUpdated;
+ ///
+ /// Initializes a new instance of the class with a single server URL.
+ ///
+ /// The URL of the remote server.
+ /// An action to configure the executor options.
public RemoteExecutor(string url, Action configure) : this([url], NullLogger.Instance, configure)
{
}
+ ///
+ /// Initializes a new instance of the class with a single server URL and logger.
+ ///
+ /// The URL of the remote server.
+ /// The logger instance.
+ /// An action to configure the executor options.
public RemoteExecutor(string url, ILogger logger, Action configure) : this([url], logger, configure)
{
}
+ ///
+ /// Initializes a new instance of the class with multiple server URLs.
+ ///
+ /// The URLs of the remote servers.
+ /// An action to configure the executor options.
public RemoteExecutor(string[] urls, Action configure) : this(urls, NullLogger.Instance, configure)
{
}
+ ///
+ /// Initializes a new instance of the class with multiple server URLs and logger.
+ ///
+ /// The URLs of the remote servers.
+ /// The logger instance.
+ /// An action to configure the executor options.
public RemoteExecutor(string[] urls, ILogger logger, Action configure)
{
this.logger = logger;
@@ -53,6 +81,12 @@ public partial class RemoteExecutor : IAsyncDisposable
InitializeServers(urls);
}
+ ///
+ /// Initializes a new instance of the class with preconfigured options.
+ ///
+ /// The URLs of the remote servers.
+ /// The executor options.
+ /// The logger instance.
public RemoteExecutor(string[] urls, RemoteExecutorOptions options, ILogger logger)
{
this.logger = logger;
@@ -99,6 +133,10 @@ public partial class RemoteExecutor : IAsyncDisposable
}
}
+ ///
+ /// Gets the current metrics for all connected servers.
+ ///
+ /// A dictionary mapping server IDs to their metrics.
public Dictionary GetCurrentServerMetrics()
{
return servers
@@ -107,6 +145,15 @@ public partial class RemoteExecutor : IAsyncDisposable
.ToDictionary(metrics => metrics!.ServerId, metrics => metrics!);
}
+ ///
+ /// Executes a delegate remotely and returns the strongly-typed result.
+ ///
+ /// The delegate type.
+ /// The return type.
+ /// The delegate to execute.
+ /// A cancellation token to cancel the operation.
+ /// The arguments to pass to the method.
+ /// The result of the remote execution.
public async Task ExecuteAsync(TDelegate @delegate, CancellationToken cancellationToken, params object[] args) where TDelegate : Delegate
{
object? execResult = await ExecuteAsync(@delegate, cancellationToken, args);
@@ -125,11 +172,29 @@ public partial class RemoteExecutor : IAsyncDisposable
}
}
+ ///
+ /// Executes a delegate remotely and returns the strongly-typed result.
+ ///
+ /// The delegate type.
+ /// The return type.
+ /// The delegate to execute.
+ /// The arguments to pass to the method.
+ /// The result of the remote execution.
public async Task ExecuteAsync(TDelegate @delegate, params object[] args) where TDelegate : Delegate
{
return await ExecuteAsync(@delegate, CancellationToken.None, args);
}
+ ///
+ /// Executes a delegate remotely and returns the result.
+ ///
+ /// The delegate type.
+ /// The delegate to execute. Must be a static method.
+ /// A cancellation token to cancel the operation.
+ /// The arguments to pass to the method.
+ /// The result of the remote execution.
+ /// Thrown when the delegate is not a static method or uses a dynamic assembly.
+ /// Thrown when the remote execution fails.
public async Task