fix(dcl): cancel old event loop + dispose old MxGateway client on reconnect (S1)

This commit is contained in:
Joseph Doherty
2026-07-08 23:19:11 -04:00
parent 11eb5157e6
commit a8a01f026b
2 changed files with 77 additions and 0 deletions
@@ -67,6 +67,27 @@ public class MxGatewayDataConnection : IDataConnection, IBrowsableDataConnection
public async Task ConnectAsync(IDictionary<string, string> connectionDetails, CancellationToken cancellationToken = default)
{
var cfg = MxGatewayEndpointConfigSerializer.FromFlatDict(connectionDetails);
// Reconnect reuses this adapter: cancel the previous event loop and dispose
// the previous client so a flapping gateway cannot accumulate orphaned
// streams/sockets, and the old loop's fault path cannot signal Disconnected
// against the new session after the guard resets below. Keep this BEFORE the
// _disconnectFired reset so a fault raised by the dying loop during teardown
// is absorbed by the old guard cycle. Dispose is best-effort fire-and-forget.
if (_eventLoopCts is { } previousLoopCts)
{
previousLoopCts.Cancel();
previousLoopCts.Dispose();
_eventLoopCts = null;
}
if (_client is { } previousClient)
{
_ = previousClient.DisposeAsync().AsTask().ContinueWith(
t => _logger.LogWarning(t.Exception?.GetBaseException(),
"Disposing previous MxGateway client failed"),
TaskContinuationOptions.OnlyOnFaulted);
}
Interlocked.Exchange(ref _disconnectFired, 0); // reset guard on (re)connect, like OPC UA
_client = _clientFactory.Create();