using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; using ZB.MOM.WW.ScadaBridge.HealthMonitoring; namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests.TestSupport; /// /// Minimal whose only job is to expose the observable edge /// "the Deployment Manager's boot-time config load has PROVABLY read storage". The manager calls /// unconditionally the moment that load finishes — including for /// an empty site — so a non-zero replaces a wall-clock sleep. /// /// /// Why every post-boot start-path test must gate on this (deferred register rows 83 + 78). /// A test that writes a deployed_configurations row BEFORE that read lands has its row /// picked up by the boot load itself — so the test passes while proving the boot load works, /// not the post-boot path (startup reconcile, sweep, enable) it claims to cover. A bare /// Task.Delay only makes that race unlikely, not impossible: on a loaded machine the load /// can still be in flight when the delay expires, and the test silently changes what it proves /// instead of failing. Gating on the first instance-count report removes the race entirely. /// /// public sealed class DeploymentManagerStartupProbe : ISiteHealthCollector { private int _reports; /// /// Number of calls seen. Greater than zero means the /// boot-time config load has completed and read storage. /// public int ReportCount => Volatile.Read(ref _reports); /// public void SetInstanceCounts(int deployed, int enabled, int disabled) => Interlocked.Increment(ref _reports); /// public void IncrementScriptError() { } /// public void IncrementAlarmError() { } /// public void IncrementDeadLetter() { } /// public void IncrementSiteAuditWriteFailures() { } /// public void IncrementAuditRedactionFailure() { } /// public void UpdateSiteAuditBacklog(Commons.Types.SiteAuditBacklogSnapshot snapshot) { } /// public void UpdateConnectionHealth(string connectionName, ConnectionHealth health) { } /// public void RemoveConnection(string connectionName) { } /// public void UpdateTagResolution(string connectionName, int totalSubscribed, int successfullyResolved) { } /// public void UpdateConnectionEndpoint(string connectionName, string endpoint) { } /// public void UpdateTagQuality(string connectionName, int good, int bad, int uncertain) { } /// public void SetStoreAndForwardDepths(IReadOnlyDictionary depths) { } /// public void SetParkedMessageCount(int count) { } /// public void SetNodeHostname(string hostname) { } /// public void SetClusterNodes(IReadOnlyList nodes) { } /// public void SetActiveNode(bool isActive) { } /// public bool IsActiveNode => true; /// public Commons.Messages.Health.SiteHealthReport CollectReport(string siteId) => throw new NotSupportedException("Startup probe collects no report."); }