Fix second-pass review findings: subscription leak on rebuild, metrics accuracy, and MxAccess startup recovery

- Preserve and replay subscription ref counts across address space rebuilds to prevent MXAccess subscription leaks
- Mark read timeouts and write failures as unsuccessful in PerformanceMetrics for accurate health reporting
- Add deferred MxAccess reconnect path when initial connection fails at startup
- Update code review document with verified completions and new findings
- Add covering tests for all fixes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-03-25 09:41:12 -04:00
parent 71254e005e
commit 09ed15bdda
12 changed files with 307 additions and 51 deletions

View File

@@ -145,15 +145,21 @@ namespace ZB.MOM.WW.LmxOpcUa.Host.OpcUa
lock (Lock)
{
Log.Information("Rebuilding address space...");
var activeSubscriptions = new Dictionary<string, int>(_subscriptionRefCounts, StringComparer.OrdinalIgnoreCase);
// Remove all predefined nodes
var nodesToRemove = new List<NodeId>();
foreach (var kvp in _nodeIdToTagReference)
foreach (var tagRef in activeSubscriptions.Keys)
{
var nodeId = new NodeId(kvp.Key, NamespaceIndex);
nodesToRemove.Add(nodeId);
try
{
_mxAccessClient.UnsubscribeAsync(tagRef).GetAwaiter().GetResult();
}
catch (Exception ex)
{
Log.Warning(ex, "Failed to unsubscribe {TagRef} during rebuild", tagRef);
}
}
// Remove all predefined nodes
foreach (var nodeId in PredefinedNodes.Keys.ToList())
{
try { DeleteNode(SystemContext, nodeId); }
@@ -167,6 +173,23 @@ namespace ZB.MOM.WW.LmxOpcUa.Host.OpcUa
// Rebuild
BuildAddressSpace(hierarchy, attributes);
foreach (var kvp in activeSubscriptions)
{
if (!_tagToVariableNode.ContainsKey(kvp.Key))
continue;
try
{
_mxAccessClient.SubscribeAsync(kvp.Key, (_, _) => { }).GetAwaiter().GetResult();
_subscriptionRefCounts[kvp.Key] = kvp.Value;
}
catch (Exception ex)
{
Log.Warning(ex, "Failed to restore subscription for {TagRef} after rebuild", kvp.Key);
}
}
Log.Information("Address space rebuild complete");
}
}