Resolve all 46 low-severity architecture review findings

This commit is contained in:
Joseph Doherty
2026-09-09 22:56:36 -04:00
parent fef3e7675f
commit 9ee402bbcd
139 changed files with 2621 additions and 1082 deletions
@@ -561,18 +561,10 @@ akka {{
// 30 s timeout, so it could only add a hop and latency to every audit batch.
centralControlGrpc?.SetAuditIngestActor(auditIngest.Proxy);
// Hand the proxy to the SiteStreamGrpcServer (if registered on this node)
// so the IngestAuditEvents RPC routes incoming site batches to the singleton.
// The gRPC server is currently only registered on Site nodes; on a central
// node this resolves to null and the wiring is a no-op unless a future
// central-hosted gRPC server (or a real site→central client) is added.
var grpcServer = _serviceProvider.GetService<ZB.MOM.WW.ScadaBridge.Communication.Grpc.SiteStreamGrpcServer>();
grpcServer?.SetAuditIngestActor(auditIngest.Proxy);
_logger.LogInformation(
"AuditLogIngestActor singleton created (control-plane bound: {ControlBound}, "
+ "site-stream server bound: {GrpcBound})",
centralControlGrpc is not null,
grpcServer is not null);
"AuditLogIngestActor singleton created (control-plane bound: {ControlBound})",
centralControlGrpc is not null);
// Subscribe the per-site stalled
// telemetry tracker to the actor system EventStream NOW that the
@@ -121,8 +121,10 @@ public sealed class ClusterBootstrapCoordinator : IHostedService
return;
}
ct.ThrowIfCancellationRequested();
var cluster = Akka.Cluster.Cluster.Get(_system());
var addresses = order.Select(Address.Parse).ToArray();
ct.ThrowIfCancellationRequested();
cluster.JoinSeedNodes(addresses);
// Peer-first is a one-way commitment: JoinSeedNodeProcess never self-forms. If the founder
@@ -184,7 +186,7 @@ public sealed class ClusterBootstrapCoordinator : IHostedService
if (await TryConnectAsync(host, port, ct).ConfigureAwait(false)) return true;
if (sw.Elapsed >= window) return false;
try { await Task.Delay(interval, ct).ConfigureAwait(false); }
catch (OperationCanceledException) { return false; }
catch (OperationCanceledException) when (ct.IsCancellationRequested) { throw; }
}
return false;
}
@@ -29,12 +29,13 @@ namespace ZB.MOM.WW.ScadaBridge.Host.Health;
/// whole check stays cheap and readiness polling stays fast.
/// </para>
/// <para>
/// <b>Required-always vs if-applicable.</b> All five central singleton proxies are
/// created unconditionally on a central node (there is no feature/config gate around
/// any of them), so all five are treated as required-always here. If a future
/// singleton is created behind a feature flag, it should NOT be added to
/// <see cref="RequiredSingletonProxyNames"/> — "if applicable" means skip when its
/// feature is off.
/// <b>Required versus best-effort.</b> Seven central singleton proxies are created
/// unconditionally. The five listed in <see cref="RequiredSingletonProxyNames"/>
/// are required for readiness. The KPI-history recorder and pending-deployment purge
/// are deliberately excluded: they provide best-effort observability and hygiene,
/// respectively, and their availability is not a correctness prerequisite. Future
/// additions must be classified by readiness impact, not just unconditional creation;
/// a feature-gated singleton must also be skipped when its feature is disabled.
/// </para>
/// <para>
/// <b>Failover flakiness.</b> During a brief singleton handover the singleton may be
@@ -60,7 +61,7 @@ public sealed class RequiredSingletonsHealthCheck : IHealthCheck
/// <summary>
/// Local actor names (under <c>/user</c>) of the <c>ClusterSingletonProxy</c>
/// actors for the singletons that must always be running on a central node.
/// Matches the unconditional proxy registrations in
/// Selects the five required services from the seven unconditional registrations in
/// <c>AkkaHostedService.RegisterCentralActors</c>.
/// </summary>
public static readonly IReadOnlyList<string> RequiredSingletonProxyNames = new[]
@@ -230,6 +230,8 @@ try
builder.WebHost.ConfigureKestrel(options =>
{
options.Limits.Http2.KeepAlivePingDelay = SiteKestrelSetup.Http2KeepAlivePingDelay;
options.Limits.Http2.KeepAlivePingTimeout = SiteKestrelSetup.Http2KeepAlivePingTimeout;
// The HTTP/1.1 (+ HTTP/2) surface from the configured URLs, re-declared so it
// survives the explicit-endpoints switch above.
foreach (var httpPort in httpPorts)