diff --git a/lmxproxy/src/ZB.MOM.WW.LmxProxy.Host/Subscriptions/SubscriptionManager.cs b/lmxproxy/src/ZB.MOM.WW.LmxProxy.Host/Subscriptions/SubscriptionManager.cs index bbcfb40..4a9194f 100644 --- a/lmxproxy/src/ZB.MOM.WW.LmxProxy.Host/Subscriptions/SubscriptionManager.cs +++ b/lmxproxy/src/ZB.MOM.WW.LmxProxy.Host/Subscriptions/SubscriptionManager.cs @@ -57,8 +57,8 @@ namespace ZB.MOM.WW.LmxProxy.Host.Subscriptions }); var addressSet = new HashSet(addresses, StringComparer.OrdinalIgnoreCase); - var clientSub = new ClientSubscription(clientId, channel, addressSet); + var clientSub = new ClientSubscription(clientId, channel, addressSet); _clientSubscriptions[clientId] = clientSub; var newTags = new List(); @@ -170,17 +170,18 @@ namespace ZB.MOM.WW.LmxProxy.Host.Subscriptions _rwLock.EnterWriteLock(); try { - foreach (var address in clientSub.Addresses) + // Scan all tag subscriptions — not just clientSub.Addresses — because + // a client may have called Subscribe multiple times (one tag per RPC), + // each overwriting the ClientSubscription. The last one's Addresses + // only has the final batch, but earlier tags still reference this client. + foreach (var kvp in _tagSubscriptions) { - if (_tagSubscriptions.TryGetValue(address, out var tagSub)) + if (kvp.Value.ClientIds.Remove(clientId)) { - tagSub.ClientIds.Remove(clientId); - - // Last client unsubscribed — remove the tag subscription - if (tagSub.ClientIds.Count == 0) + if (kvp.Value.ClientIds.Count == 0) { - _tagSubscriptions.TryRemove(address, out _); - tagsToDispose.Add(address); + _tagSubscriptions.TryRemove(kvp.Key, out _); + tagsToDispose.Add(kvp.Key); } } }