namespace Explorer.Analysis; internal sealed class AnalysisResultCache { private const int MaxEntries = 32; private static readonly TimeSpan Ttl = TimeSpan.FromSeconds(20); private readonly object _gate = new(); private readonly Dictionary _items = new(StringComparer.Ordinal); public bool TryGet(string key, long stamp, out T value) { lock (_gate) { if (_items.TryGetValue(key, out var entry) && entry.Stamp == stamp && entry.Utc + Ttl > DateTime.UtcNow && entry.Value is T typed) { value = typed; return true; } } value = default!; return false; } public void Set(string key, long stamp, T value) { lock (_gate) { _items[key] = new Entry(stamp, value!, DateTime.UtcNow); if (_items.Count <= MaxEntries) { return; } var oldest = _items.OrderBy(p => p.Value.Utc).First().Key; _items.Remove(oldest); } } private readonly record struct Entry(long Stamp, object Value, DateTime Utc); }