feat(gateway): configurable worker write-completion wait (MxGateway:Worker:WriteCompletionWaitMilliseconds)
This commit is contained in:
@@ -225,6 +225,10 @@ public sealed class GatewayOptionsValidator : OptionsValidatorBase<GatewayOption
|
||||
options.PipeConnectAttemptTimeoutMilliseconds,
|
||||
"MxGateway:Worker:PipeConnectAttemptTimeoutMilliseconds must be greater than zero.",
|
||||
builder);
|
||||
if (options.WriteCompletionWaitMilliseconds < 0)
|
||||
{
|
||||
builder.Add("MxGateway:Worker:WriteCompletionWaitMilliseconds must be greater than or equal to zero.");
|
||||
}
|
||||
AddIfNotPositive(
|
||||
options.ShutdownTimeoutSeconds,
|
||||
"MxGateway:Worker:ShutdownTimeoutSeconds must be greater than zero.",
|
||||
|
||||
@@ -24,6 +24,15 @@ public sealed class WorkerOptions
|
||||
/// <summary>The timeout in milliseconds for connecting to the worker pipe.</summary>
|
||||
public int PipeConnectAttemptTimeoutMilliseconds { get; init; } = 2000;
|
||||
|
||||
/// <summary>
|
||||
/// Bounded wait, in milliseconds, the worker holds a WriteSecured/WriteSecured2
|
||||
/// reply for the matching MXAccess OnWriteComplete callback so the reply's
|
||||
/// statuses carry the real commit outcome. 0 disables the wait. Deployments
|
||||
/// raising this above consumer write-timeout budgets (e.g. OtOpcUa's 2 s Tier A
|
||||
/// write resilience timeout) must raise those in step.
|
||||
/// </summary>
|
||||
public int WriteCompletionWaitMilliseconds { get; init; } = 1500;
|
||||
|
||||
/// <summary>The maximum time in seconds for graceful shutdown.</summary>
|
||||
public int ShutdownTimeoutSeconds { get; init; } = 10;
|
||||
|
||||
|
||||
@@ -21,6 +21,14 @@ public sealed class WorkerProcessLauncher : IWorkerProcessLauncher
|
||||
public const string WorkerPipeConnectAttemptTimeoutEnvironmentVariableName =
|
||||
"MXGATEWAY_WORKER_PIPE_CONNECT_ATTEMPT_TIMEOUT_MS";
|
||||
|
||||
/// <summary>
|
||||
/// Conveys MxGateway:Worker:WriteCompletionWaitMilliseconds to the worker:
|
||||
/// the bounded wait for the OnWriteComplete callback on
|
||||
/// WriteSecured/WriteSecured2 replies. 0 disables the wait.
|
||||
/// </summary>
|
||||
public const string WorkerWriteCompletionWaitEnvironmentVariableName =
|
||||
"MXGATEWAY_WORKER_WRITE_COMPLETION_WAIT_MS";
|
||||
|
||||
private readonly IWorkerProcessFactory _processFactory;
|
||||
private readonly IWorkerStartupProbe _startupProbe;
|
||||
private readonly GatewayMetrics _metrics;
|
||||
@@ -175,6 +183,8 @@ public sealed class WorkerProcessLauncher : IWorkerProcessLauncher
|
||||
startInfo.Environment[WorkerNonceEnvironmentVariableName] = request.Nonce;
|
||||
startInfo.Environment[WorkerPipeConnectAttemptTimeoutEnvironmentVariableName] =
|
||||
_workerOptions.PipeConnectAttemptTimeoutMilliseconds.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
||||
startInfo.Environment[WorkerWriteCompletionWaitEnvironmentVariableName] =
|
||||
_workerOptions.WriteCompletionWaitMilliseconds.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
||||
|
||||
commandLine = new WorkerProcessCommandLine(executablePath, arguments);
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ public sealed class GatewayOptionsTests
|
||||
Assert.Equal(3, options.Worker.StartupProbeRetryAttempts);
|
||||
Assert.Equal(250, options.Worker.StartupProbeRetryDelayMilliseconds);
|
||||
Assert.Equal(2000, options.Worker.PipeConnectAttemptTimeoutMilliseconds);
|
||||
Assert.Equal(1500, options.Worker.WriteCompletionWaitMilliseconds);
|
||||
Assert.Equal(10, options.Worker.ShutdownTimeoutSeconds);
|
||||
Assert.Equal(5, options.Worker.HeartbeatIntervalSeconds);
|
||||
Assert.Equal(15, options.Worker.HeartbeatGraceSeconds);
|
||||
@@ -106,6 +107,7 @@ public sealed class GatewayOptionsTests
|
||||
[InlineData("MxGateway:Worker:ExecutablePath", "worker.dll", "MxGateway:Worker:ExecutablePath must point to a .exe file.")]
|
||||
[InlineData("MxGateway:Worker:StartupProbeRetryAttempts", "0", "MxGateway:Worker:StartupProbeRetryAttempts must be greater than zero.")]
|
||||
[InlineData("MxGateway:Worker:PipeConnectAttemptTimeoutMilliseconds", "0", "MxGateway:Worker:PipeConnectAttemptTimeoutMilliseconds must be greater than zero.")]
|
||||
[InlineData("MxGateway:Worker:WriteCompletionWaitMilliseconds", "-1", "MxGateway:Worker:WriteCompletionWaitMilliseconds must be greater than or equal to zero.")]
|
||||
[InlineData("MxGateway:Sessions:DefaultLeaseSeconds", "0", "MxGateway:Sessions:DefaultLeaseSeconds must be greater than zero.")]
|
||||
[InlineData("MxGateway:Sessions:LeaseSweepIntervalSeconds", "0", "MxGateway:Sessions:LeaseSweepIntervalSeconds must be greater than zero.")]
|
||||
[InlineData("MxGateway:Sessions:DetachGraceSeconds", "-1", "MxGateway:Sessions:DetachGraceSeconds must be zero or greater (0 disables detach-grace retention).")]
|
||||
|
||||
@@ -43,6 +43,10 @@ public sealed class WorkerProcessLauncherTests
|
||||
"2000",
|
||||
processFactory.LastStartInfo.Environment[
|
||||
WorkerProcessLauncher.WorkerPipeConnectAttemptTimeoutEnvironmentVariableName]);
|
||||
Assert.Equal(
|
||||
"1500",
|
||||
processFactory.LastStartInfo.Environment[
|
||||
WorkerProcessLauncher.WorkerWriteCompletionWaitEnvironmentVariableName]);
|
||||
Assert.DoesNotContain(Nonce, handle.CommandLine.ToString(), StringComparison.Ordinal);
|
||||
Assert.DoesNotContain(Nonce, string.Join(" ", handle.CommandLine.Arguments), StringComparison.Ordinal);
|
||||
Assert.False(pipeReservation.DisposeCalled);
|
||||
|
||||
Reference in New Issue
Block a user