Storage queries run in the background with cancellation and covering indexes so switching views no longer freezes the UI. Co-authored-by: Cursor <cursoragent@cursor.com>
46 lines
1.2 KiB
C#
46 lines
1.2 KiB
C#
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<string, Entry> _items = new(StringComparer.Ordinal);
|
|
|
|
public bool TryGet<T>(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<T>(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);
|
|
}
|