using System; namespace ZB.MOM.WW.MxGateway.Worker.Ipc; /// Configuration options for worker pipe sessions including heartbeat parameters. public sealed class WorkerPipeSessionOptions { /// Default heartbeat interval (5 seconds). public static readonly TimeSpan DefaultHeartbeatInterval = TimeSpan.FromSeconds(5); /// Default heartbeat grace period (15 seconds). public static readonly TimeSpan DefaultHeartbeatGrace = TimeSpan.FromSeconds(15); /// /// Default defensive ceiling beyond which the watchdog fires /// /// even while a command is in flight (75 seconds = 5 × /// ). See /// for the rationale. /// public static readonly TimeSpan DefaultHeartbeatStuckCeiling = TimeSpan.FromSeconds(75); /// Initializes a new instance of the WorkerPipeSessionOptions class with default values. public WorkerPipeSessionOptions() { HeartbeatInterval = DefaultHeartbeatInterval; HeartbeatGrace = DefaultHeartbeatGrace; HeartbeatStuckCeiling = DefaultHeartbeatStuckCeiling; } /// Gets or sets the heartbeat interval. public TimeSpan HeartbeatInterval { get; set; } /// Gets or sets the heartbeat grace period. public TimeSpan HeartbeatGrace { get; set; } /// /// Gets or sets the defensive upper bound on how long the watchdog /// will suppress its StaHung fault while a command is in /// flight. Worker-017 suppresses the watchdog when the heartbeat /// snapshot's CurrentCommandCorrelationId is non-empty so a /// legitimately slow command (e.g. ReadBulk against many /// uncached tags) does not self-fault — but a truly stuck /// synchronous COM call against a dead MXAccess provider leaves /// CurrentCommandCorrelationId non-empty forever and would /// permanently defeat the watchdog. HeartbeatStuckCeiling is /// the upper bound on that suppression: once /// LastStaActivityUtc has been stale for longer than this /// ceiling, the watchdog DOES fire StaHung even with a /// command in flight, on the assumption that no legitimate STA /// command should run that long without periodically refreshing /// activity. Default is /// (75 seconds = 5 × ); raise /// for deployments that run very long bulk operations. /// public TimeSpan HeartbeatStuckCeiling { get; set; } /// Validates the session options. 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."); } } }