worker(alarms): net48 index fix; enforce ProbeIntervalSeconds; OOM-safe catch; reset-on-failure test

This commit is contained in:
Joseph Doherty
2026-06-13 09:55:07 -04:00
parent d6c0bb41ca
commit 7241a4fb9c
2 changed files with 53 additions and 4 deletions
@@ -63,6 +63,7 @@ public sealed class FailoverAlarmConsumer : IMxAccessAlarmConsumer
private int consecutiveFailures;
private int cleanProbes;
private bool disposed;
private DateTime lastProbeAtUtc = DateTime.MinValue;
/// <summary>
/// The subscription expression passed to <see cref="Subscribe"/>.
@@ -177,6 +178,16 @@ public sealed class FailoverAlarmConsumer : IMxAccessAlarmConsumer
/// drive it directly.
/// </para>
/// <para>
/// <strong>Probe throttle.</strong> When
/// <see cref="FailoverSettings.ProbeIntervalSeconds"/> is greater than
/// zero, successive calls to this method are throttled: a probe is
/// skipped unless at least that many seconds have elapsed since the
/// last probe that was actually executed. When
/// <see cref="FailoverSettings.ProbeIntervalSeconds"/> is zero, the
/// throttle is disabled and every call probes immediately (the default
/// used by unit tests).
/// </para>
/// <para>
/// <strong>Why PollOnce only — no re-Subscribe.</strong>
/// Failover does NOT tear down the primary's subscription;
/// <see cref="WnWrapAlarmConsumer"/> is single-subscribe and would
@@ -202,6 +213,16 @@ public sealed class FailoverAlarmConsumer : IMxAccessAlarmConsumer
if (disposed) throw new ObjectDisposedException(nameof(FailoverAlarmConsumer));
if (active != Active.Standby) return;
// Throttle probes to the configured cadence. When ProbeIntervalSeconds
// is 0 the throttle is disabled and every call probes immediately.
if (settings.ProbeIntervalSeconds > 0
&& (DateTime.UtcNow - lastProbeAtUtc).TotalSeconds < settings.ProbeIntervalSeconds)
{
return;
}
lastProbeAtUtc = DateTime.UtcNow;
try
{
// Re-poll the still-subscribed primary. Do NOT call Subscribe —
@@ -278,7 +299,7 @@ public sealed class FailoverAlarmConsumer : IMxAccessAlarmConsumer
{
action();
}
catch (Exception ex)
catch (Exception ex) when (ex is not OutOfMemoryException)
{
consecutiveFailures++;
int hresult = ex is COMException ? ex.HResult : 0;