Files
mxaccessgw/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeSessionOptions.cs
T
Joseph Doherty dc9c0c950c rename: prefix gateway projects/namespaces with ZB.MOM.WW + sln→slnx
Apply the ZB.MOM.WW. prefix to all gateway-side projects, folders,
.csproj/.sln contents, C# namespaces, using directives, generated proto
C# (csharp_namespace + checked-in generated files), InternalsVisibleTo
attributes, project-name string literals (LoadProject, .sln lookups,
worker exe paths, staticwebassets manifest), and the install/script/doc
references that point at any of the above. Migrate the solution from
.sln to .slnx via `dotnet sln migrate` and delete the old file.

External-runtime identifiers are intentionally NOT prefixed so external
configuration keeps working:
- GatewayMetrics.cs MeterName ("MxGateway.Server")
- DashboardAuthenticationDefaults Scheme/Policy ("MxGateway.Dashboard")
- GatewayRequestLoggingMiddleware logger category ("MxGateway.Request")
- StaRuntime thread name ("MxGateway.Worker.STA")
- appsettings.json root section "MxGateway" + env-var prefix
  MxGateway__... and secret-name MxGateway:ApiKeyPepper
- C:\ProgramData\MxGateway\ data dir paths

Also fixes two tests that were not rename-related but became visible
while validating the rename:

- WorkerLiveMxAccessSmokeTests.ShutDownAsync: cancellation that the
  gateway service correctly maps to RpcException(Cancelled) per gRPC
  convention was being misclassified as a stream fault. Added a sibling
  catch on RpcException with StatusCode.Cancelled.

- IntegrationTestEnvironment.ResolveRepositoryRoot: extracted IsRepositoryRoot
  and made it accept either a .git marker OR a .sln/.slnx next to src/
  so the worker-exe walker works in non-git working copies.

clients/proto/proto-inputs.json's protoRoot updated to point at
src/ZB.MOM.WW.MxGateway.Contracts/Protos.

Verified by `dotnet build` and a full `dotnet test` of the .slnx with
MXGATEWAY_RUN_LIVE_{MXACCESS,LDAP,GALAXY}_TESTS=1:
  Tests: 472/472 pass
  Worker.Tests: 280/280 pass (4 dev-rig [Fact(Skip=...)] skipped)
  IntegrationTests: 18/18 pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 16:22:23 -04:00

89 lines
4.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
namespace ZB.MOM.WW.MxGateway.Worker.Ipc;
/// <summary>Configuration options for worker pipe sessions including heartbeat parameters.</summary>
public sealed class WorkerPipeSessionOptions
{
/// <summary>Default heartbeat interval (5 seconds).</summary>
public static readonly TimeSpan DefaultHeartbeatInterval = TimeSpan.FromSeconds(5);
/// <summary>Default heartbeat grace period (15 seconds).</summary>
public static readonly TimeSpan DefaultHeartbeatGrace = TimeSpan.FromSeconds(15);
/// <summary>
/// Default defensive ceiling beyond which the watchdog fires
/// <see cref="ZB.MOM.WW.MxGateway.Contracts.Proto.WorkerFaultCategory.StaHung"/>
/// even while a command is in flight (75 seconds = 5 ×
/// <see cref="DefaultHeartbeatGrace"/>). See <see cref="HeartbeatStuckCeiling"/>
/// for the rationale.
/// </summary>
public static readonly TimeSpan DefaultHeartbeatStuckCeiling = TimeSpan.FromSeconds(75);
/// <summary>Initializes a new instance of the WorkerPipeSessionOptions class with default values.</summary>
public WorkerPipeSessionOptions()
{
HeartbeatInterval = DefaultHeartbeatInterval;
HeartbeatGrace = DefaultHeartbeatGrace;
HeartbeatStuckCeiling = DefaultHeartbeatStuckCeiling;
}
/// <summary>Gets or sets the heartbeat interval.</summary>
public TimeSpan HeartbeatInterval { get; set; }
/// <summary>Gets or sets the heartbeat grace period.</summary>
public TimeSpan HeartbeatGrace { get; set; }
/// <summary>
/// Gets or sets the defensive upper bound on how long the watchdog
/// will suppress its <c>StaHung</c> fault while a command is in
/// flight. Worker-017 suppresses the watchdog when the heartbeat
/// snapshot's <c>CurrentCommandCorrelationId</c> is non-empty so a
/// legitimately slow command (e.g. <c>ReadBulk</c> against many
/// uncached tags) does not self-fault — but a truly stuck
/// synchronous COM call against a dead MXAccess provider leaves
/// <c>CurrentCommandCorrelationId</c> non-empty forever and would
/// permanently defeat the watchdog. <c>HeartbeatStuckCeiling</c> is
/// the upper bound on that suppression: once
/// <c>LastStaActivityUtc</c> has been stale for longer than this
/// ceiling, the watchdog DOES fire <c>StaHung</c> even with a
/// command in flight, on the assumption that no legitimate STA
/// command should run that long without periodically refreshing
/// activity. Default is <see cref="DefaultHeartbeatStuckCeiling"/>
/// (75 seconds = 5 × <see cref="DefaultHeartbeatGrace"/>); raise
/// for deployments that run very long bulk operations.
/// </summary>
public TimeSpan HeartbeatStuckCeiling { get; set; }
/// <summary>Validates the session options.</summary>
public void Validate()
{
if (HeartbeatInterval <= TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(
nameof(HeartbeatInterval),
"Worker heartbeat interval must be greater than zero.");
}
if (HeartbeatGrace <= TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(
nameof(HeartbeatGrace),
"Worker heartbeat grace must be greater than zero.");
}
if (HeartbeatStuckCeiling <= TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(
nameof(HeartbeatStuckCeiling),
"Worker heartbeat stuck ceiling must be greater than zero.");
}
if (HeartbeatStuckCeiling <= HeartbeatGrace)
{
throw new ArgumentOutOfRangeException(
nameof(HeartbeatStuckCeiling),
"Worker heartbeat stuck ceiling must be greater than HeartbeatGrace; "
+ "otherwise it would fire before the in-flight-command suppression had any effect.");
}
}
}