namespace ZB.MOM.WW.ScadaBridge.HealthMonitoring;
public class HealthMonitoringOptions
{
/// Interval at which sites emit health reports to the central cluster.
public TimeSpan ReportInterval { get; set; } = TimeSpan.FromSeconds(30);
/// Duration of silence after which a site is classified as offline.
public TimeSpan OfflineTimeout { get; set; } = TimeSpan.FromMinutes(1);
///
/// Offline timeout applied to the synthetic "central" site only. Real sites
/// emit frequent heartbeats that keep LastHeartbeatAt fresh, so the
/// normal only fires on genuine total loss. The
/// "central" self-report has no heartbeat source — its only signal is the
/// 30s , so a single skipped/late
/// self-report (leader GC pause, brief stall, mid-failover before the new
/// leader's loop spins up) would flap it offline under the 60s site timeout.
/// A longer central grace gives the equivalent of "one missed report" that
/// the design doc grants real sites. Default: 3x the report interval.
///
public TimeSpan CentralOfflineTimeout { get; set; } = TimeSpan.FromMinutes(3);
///
/// Duration an online site may go without a full health report
/// (heartbeats notwithstanding) before it is flagged
/// . Distinct from
/// , which is heartbeat-based liveness: a site
/// whose HealthReportSender has died keeps heartbeating and stays "online",
/// but its metrics freeze — this window surfaces that. Must be positive and
/// no shorter than (a window shorter than one
/// report interval would flag every healthy site). Default: 2 minutes
/// (~4 missed 30s reports).
///
public TimeSpan MetricsStaleTimeout { get; set; } = TimeSpan.FromMinutes(2);
///
/// Unacked LocalDb replication oplog depth above which a site is considered backlogged
/// (register row 33). Crossing this alone shows nothing — the backlog must also stay
/// above it for before the Health dashboard
/// badges the site. Must be positive. Default: 1000 entries.
///
public long LocalDbBacklogThreshold { get; set; } = 1000;
///
/// How long the oplog backlog must stay continuously above
/// before the Health dashboard badges the site
/// (register row 33).
///
///
/// This dwell time is the whole point of the signal, not a refinement of it. A bare
/// threshold would fire every single day on a healthy replicated site: the `site_events`
/// retention purge and the storage-cap trim are CDC-captured like any other write, so the
/// backlog jumps by the deleted batch size and then drains as the peer acks it. That spike
/// is expected and documented (see docs/deployment/topology-guide.md → *Reading the
/// replication backlog*). Healthy means the backlog RETURNS TO ~0; unhealthy means it
/// stays up. Only a sustained window can tell those apart, so the default is set well
/// clear of a purge drain. Must be positive and no shorter than
/// — a window shorter than one report interval could be
/// satisfied by a single sample, which is exactly the bare threshold this exists to avoid.
/// Default: 15 minutes.
///
public TimeSpan LocalDbBacklogSustainedFor { get; set; } = TimeSpan.FromMinutes(15);
}