fix(runtime): comms-loss grace is per connection — max(LastSuccessfulRead, connectedSince) (archreview 03/S17)
This commit is contained in:
@@ -561,6 +561,19 @@ public sealed class DriverInstanceActor : ReceiveActor, IWithTimers
|
||||
/// state on sustained failure: the nine poll drivers via Degraded, MQTT via its live connection
|
||||
/// state, Galaxy via its reconnect supervisor.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <b>The grace is per CONNECTION (03/S17).</b> The silence baseline is
|
||||
/// <c>max(LastSuccessfulRead, _connectedSinceUtc)</c>, not <c>LastSuccessfulRead ?? _connectedSinceUtc</c>.
|
||||
/// Because <c>LastSuccessfulRead</c> is <em>preserved</em> across Degraded/Faulted writes (see above),
|
||||
/// a device that accepts a connection but serves no data reconnects carrying a stamp that is already
|
||||
/// older than the threshold, so a <c>??</c> baseline re-trips on the FIRST health tick of every new
|
||||
/// connection — a reconnect cycle at health-tick cadence rather than the designed threshold. Taking
|
||||
/// the later of the two gives each connection its own full window, which is exactly what re-stamping
|
||||
/// <c>_connectedSinceUtc</c> on every Connected entry was for. Note this <b>paces</b> the cycle, it
|
||||
/// does not end it: a permanently half-broken device still reconnects once per threshold, and a
|
||||
/// driver that stops reading <i>within</i> a stable connection still trips on schedule (its read
|
||||
/// stamp is the later term, exactly as before).
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="health">The health observed on this tick, or null when <see cref="IDriver.GetHealth"/>
|
||||
/// threw — a failed observation is not evidence of comms loss, so it never advances the watchdog.</param>
|
||||
@@ -570,8 +583,15 @@ public sealed class DriverInstanceActor : ReceiveActor, IWithTimers
|
||||
if (health is not { } observed) return;
|
||||
if (observed.State == DriverState.Healthy) return;
|
||||
|
||||
// A driver that has never reported a successful read is measured from the current Connected entry.
|
||||
var lastEvidence = observed.LastSuccessfulRead ?? _connectedSinceUtc;
|
||||
// Measure silence from the LATER of the last successful read and THIS connect — the grace is per
|
||||
// connection. `??` was wrong: drivers PRESERVE LastSuccessfulRead across Degraded/Faulted writes (that
|
||||
// preservation is the #527 design), so after a trip + reconnect to a device that accepts the connection
|
||||
// but still serves no data, the stamp is already older than the threshold and the FIRST tick of the new
|
||||
// connection re-trips — churn at health-tick cadence instead of the designed grace. `??` only ever helped
|
||||
// a driver that had never read at all.
|
||||
var lastEvidence = observed.LastSuccessfulRead is { } read && read > _connectedSinceUtc
|
||||
? read
|
||||
: _connectedSinceUtc;
|
||||
var silence = DateTime.UtcNow - lastEvidence;
|
||||
if (silence < _commsLossTimeout) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user