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