perf(comms+audit): close phase-2 residuals — direct ingest path, monotonic timeouts, synthetic probe, not-reporting set, cursor-exact audit pull

This commit is contained in:
Joseph Doherty
2026-08-14 21:38:23 -04:00
parent 4cd1441984
commit a5882753dd
38 changed files with 1254 additions and 443 deletions
@@ -38,6 +38,15 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc;
/// </remarks>
public sealed class CentralChannelProvider : IDisposable
{
/// <summary>
/// Hostname stamped on the failback probe's heartbeat, so a central-side log line names it
/// for what it is. It is a LABEL only — the machine-readable contract is
/// <see cref="ZB.MOM.WW.ScadaBridge.Commons.Messages.Health.HeartbeatMessage.Synthetic"/>
/// (<c>HeartbeatDto.synthetic</c>, proto field 5), which central keys its skip on. Never
/// filter on this string.
/// </summary>
public const string SyntheticProbeHostname = "failback-probe";
private static readonly TimeSpan DefaultBackoffBase = TimeSpan.FromSeconds(1);
private static readonly TimeSpan DefaultBackoffCap = TimeSpan.FromSeconds(60);
private static readonly TimeSpan DefaultProbeDeadline = TimeSpan.FromSeconds(5);
@@ -202,9 +211,16 @@ public sealed class CentralChannelProvider : IDisposable
new HeartbeatDto
{
SiteId = _siteId,
NodeHostname = "failback-probe",
NodeHostname = SyntheticProbeHostname,
IsActive = false,
Timestamp = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow),
// Explicit contract, not a hostname convention: central skips ALL
// liveness/health bookkeeping for a synthetic heartbeat. Without it the
// probe would stamp the site's last-seen time on the central health
// aggregator every backoff tick, so a site whose real heartbeats had
// stopped could still look alive purely because its transport layer was
// probing for failback.
Synthetic = true,
},
deadline: DateTime.UtcNow.Add(_probeDeadline)).ConfigureAwait(false);