diff --git a/src/NATS.Server/Subscriptions/SubList.cs b/src/NATS.Server/Subscriptions/SubList.cs index 76bc149..382689b 100644 --- a/src/NATS.Server/Subscriptions/SubList.cs +++ b/src/NATS.Server/Subscriptions/SubList.cs @@ -6,16 +6,17 @@ namespace NATS.Server.Subscriptions; /// interested subscribers. Subscribers can have wildcard subjects to /// match multiple published subjects. /// -public sealed class SubList +public sealed class SubList : IDisposable { private const int CacheMax = 1024; private const int CacheSweep = 256; private readonly ReaderWriterLockSlim _lock = new(); private readonly TrieLevel _root = new(); - private Dictionary? _cache = new(); + private Dictionary? _cache = new(StringComparer.Ordinal); private uint _count; - private ulong _genId; + + public void Dispose() => _lock.Dispose(); public uint Count { @@ -84,7 +85,6 @@ public sealed class SubList } _count++; - _genId++; AddToCache(subject, sub); } finally @@ -131,7 +131,9 @@ public sealed class SubList var tokenStr = token.ToString(); pathList.Add((level, node, tokenStr, isPwc, isFwc)); - level = node.Next ?? new TrieLevel(); + if (node.Next == null) + return; // corrupted trie state + level = node.Next; } if (node == null) return; @@ -156,7 +158,6 @@ public sealed class SubList if (!removed) return; _count--; - _genId++; RemoveFromCache(sub.Subject); // Prune empty nodes (walk backwards) @@ -216,9 +217,13 @@ public sealed class SubList } else { + var queueSubsArr = new Subscription[queueSubs.Count][]; + for (int i = 0; i < queueSubs.Count; i++) + queueSubsArr[i] = queueSubs[i].ToArray(); + result = new SubListResult( plainSubs.ToArray(), - queueSubs.Select(q => q.ToArray()).ToArray()); + queueSubsArr); } if (_cache != null) @@ -498,7 +503,7 @@ public sealed class SubList private sealed class TrieLevel { - public readonly Dictionary Nodes = new(); + public readonly Dictionary Nodes = new(StringComparer.Ordinal); public TrieNode? Pwc; // partial wildcard (*) public TrieNode? Fwc; // full wildcard (>) } @@ -507,7 +512,7 @@ public sealed class SubList { public TrieLevel? Next; public readonly HashSet PlainSubs = []; - public readonly Dictionary> QueueSubs = new(); + public readonly Dictionary> QueueSubs = new(StringComparer.Ordinal); public bool IsEmpty => PlainSubs.Count == 0 && QueueSubs.Count == 0 && (Next == null || (Next.Nodes.Count == 0 && Next.Pwc == null && Next.Fwc == null));