fix(dcl): reset MxGateway alarm-stream state on reconnect so the native-alarm feed resumes (arch-review 2026-08-19 P2-2 High)

ConnectAsync reset the event loop and client on reconnect but left
_alarmCts/_alarmSubCount/_alarmSubSources/_alarmStreamPrefix untouched.
The orphaned old RunAlarmStreamAsync loop kept retrying the disposed
client every 5s forever, and SubscribeAlarmsAsync's coverage check saw
the stale state and short-circuited the actor's post-reconnect
transparent re-subscribe (ReSubscribeAllAlarms) without ever opening a
stream on the new client — freezing the native-alarm mirror until
failover/redeploy. Reset the alarm state in ConnectAsync, mirroring the
existing lock-guarded block in DisconnectAsync/DisposeAsync.
This commit is contained in:
Joseph Doherty
2026-08-19 13:45:25 -04:00
parent c4d3c8b875
commit 59468399db
2 changed files with 203 additions and 0 deletions
@@ -133,6 +133,23 @@ public class MxGatewayDataConnection
TaskContinuationOptions.OnlyOnFaulted);
}
// Same reasoning as the event loop above, but for the native-alarm feed: without
// this reset, the OLD RunAlarmStreamAsync loop keeps retrying against the now-
// disposed previous client every 5s forever (it only exits on its own token), and
// SubscribeAlarmsAsync's coverage check sees the stale _alarmCts/_alarmStreamPrefix
// and short-circuits — so the transparent re-subscribe the actor issues after a
// successful reconnect never opens a fresh stream on the NEW client. Mirror the
// lock-guarded block already in DisconnectAsync/DisposeAsync.
lock (_alarmLock)
{
_alarmCts?.Cancel();
_alarmCts?.Dispose();
_alarmCts = null;
_alarmSubCount = 0;
_alarmSubSources.Clear();
_alarmStreamPrefix = string.Empty;
}
Interlocked.Exchange(ref _disconnectFired, 0); // reset guard on (re)connect, like OPC UA
_client = _clientFactory.Create();