namespace NATS.Server.Auth; /// /// Fixed-capacity LRU cache for permission results. /// Lock-protected (per-client, low contention). /// Reference: Go client.go maxPermCacheSize=128. /// public sealed class PermissionLruCache { private readonly int _capacity; private readonly Dictionary> _map; private readonly LinkedList<(string Key, bool Value)> _list = new(); private readonly object _lock = new(); public PermissionLruCache(int capacity = 128) { _capacity = capacity; _map = new Dictionary>(capacity, StringComparer.Ordinal); } public bool TryGet(string key, out bool value) { lock (_lock) { if (_map.TryGetValue(key, out var node)) { value = node.Value.Value; _list.Remove(node); _list.AddFirst(node); return true; } value = default; return false; } } public int Count { get { lock (_lock) { return _map.Count; } } } public void Set(string key, bool value) { lock (_lock) { if (_map.TryGetValue(key, out var existing)) { _list.Remove(existing); existing.Value = (key, value); _list.AddFirst(existing); return; } if (_map.Count >= _capacity) { var last = _list.Last!; _map.Remove(last.Value.Key); _list.RemoveLast(); } var node = new LinkedListNode<(string Key, bool Value)>((key, value)); _list.AddFirst(node); _map[key] = node; } } }