Files
Musify/backend/Musify.Infrastructure/Services/SingleFlightCache.cs
T
Admin c302cfd314 perf(backend): cache YouTube searches and shrink the thumbnail URLs
Repeated searches and song lookups now reuse a single-flight memory cache, so
concurrent or debounced queries hit YouTube once instead of on every keystroke.
Thumbnails are resolved at a configurable size instead of the largest variant,
which cuts the image payload the browser pulls from Google.
2026-07-20 17:29:28 +02:00

42 lines
1.1 KiB
C#

using System.Collections.Concurrent;
using ErrorOr;
using Microsoft.Extensions.Caching.Memory;
namespace Musify.Infrastructure.Services
{
public sealed class SingleFlightCache(IMemoryCache cache)
{
private readonly ConcurrentDictionary<string, object> inFlight = new();
public async Task<ErrorOr<TValue>> GetOrCreateAsync<TValue>(
string key,
TimeSpan duration,
Func<Task<ErrorOr<TValue>>> factory)
{
if (duration <= TimeSpan.Zero)
return await factory();
if (cache.TryGetValue(key, out TValue? cached) && cached is not null)
return cached;
var pending = (Lazy<Task<ErrorOr<TValue>>>)inFlight.GetOrAdd(
key,
_ => new Lazy<Task<ErrorOr<TValue>>>(factory));
try
{
var result = await pending.Value;
if (!result.IsError)
cache.Set(key, result.Value, duration);
return result;
}
finally
{
inFlight.TryRemove(key, out _);
}
}
}
}