using JSMR.Application.Common.Caching; using JSMR.Infrastructure.Data; using Microsoft.EntityFrameworkCore; namespace JSMR.Infrastructure.Caching; public interface ICacheObject { Task GetAsync(CancellationToken cancellationToken = default); Task RefreshAsync(CancellationToken cancellationToken = default); } public abstract class CacheObject(ICache cache) : ICacheObject { protected abstract string Key { get; } protected abstract Task FetchAsync(CancellationToken cancellationToken = default); protected virtual CacheEntryOptions Options => new() { SlidingExpiration = TimeSpan.FromHours(1) }; public async virtual Task GetAsync(CancellationToken cancellationToken = default) { return await cache.GetAsync(Key, cancellationToken) ?? await RefreshAsync(cancellationToken); } public async virtual Task RefreshAsync(CancellationToken cancellationToken = default) { T cacheObject = await FetchAsync(cancellationToken); await cache.SetAsync(Key, cacheObject, Options, cancellationToken); return cacheObject; } } public interface ISpamCircleCache : ICacheObject { } public class SpamCircleCache(IDbContextFactory contextFactory, ICache cache) : CacheObject(cache), ISpamCircleCache { protected override string Key => "SpamCircles"; protected override async Task FetchAsync(CancellationToken cancellationToken = default) { using var context = contextFactory.CreateDbContext(); return await context.Circles .AsNoTracking() .Where(circle => circle.Spam) .Select(circle => circle.MakerId) .Distinct() .ToArrayAsync(cancellationToken); } }