using Microsoft.EntityFrameworkCore; using VoidCat.Model; using VoidCat.Services.Abstractions; namespace VoidCat.Services.Files; /// public class PostgresFileMetadataStore : IFileMetadataStore { private readonly VoidContext _db; private readonly IServiceScopeFactory _scopeFactory; public PostgresFileMetadataStore(VoidContext db, IServiceScopeFactory scopeFactory) { _db = db; _scopeFactory = scopeFactory; } public string? Key => "postgres"; /// public async ValueTask Get(Guid id) { return await _db.Files .AsNoTracking() .Include(a => a.Paywall) .SingleOrDefaultAsync(a => a.Id == id); } public async ValueTask Add(Database.File f) { _db.Files.Add(f); await _db.SaveChangesAsync(); } /// public async ValueTask Delete(Guid id) { await _db.Files .Where(a => a.Id == id) .ExecuteDeleteAsync(); } /// public async ValueTask> Get(Guid[] ids) { return await _db.Files .Include(a => a.Paywall) .Where(a => ids.Contains(a.Id)) .ToArrayAsync(); } /// public async ValueTask Update(Guid id, Database.File obj) { var existing = await _db.Files.FindAsync(id); if (existing == default) { return; } existing.Patch(obj); await _db.SaveChangesAsync(); } /// public async ValueTask> ListFiles(PagedRequest request) { var count = await _db.Files.CountAsync(); async IAsyncEnumerable Enumerate() { using var scope = _scopeFactory.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); var q = db.Files.AsNoTracking().AsQueryable(); switch (request.SortBy, request.SortOrder) { case (PagedSortBy.Id, PageSortOrder.Asc): q = q.OrderBy(a => a.Id); break; case (PagedSortBy.Id, PageSortOrder.Dsc): q = q.OrderByDescending(a => a.Id); break; case (PagedSortBy.Name, PageSortOrder.Asc): q = q.OrderBy(a => a.Name); break; case (PagedSortBy.Name, PageSortOrder.Dsc): q = q.OrderByDescending(a => a.Name); break; case (PagedSortBy.Date, PageSortOrder.Asc): q = q.OrderBy(a => a.Uploaded); break; case (PagedSortBy.Date, PageSortOrder.Dsc): q = q.OrderByDescending(a => a.Uploaded); break; case (PagedSortBy.Size, PageSortOrder.Asc): q = q.OrderBy(a => a.Size); break; case (PagedSortBy.Size, PageSortOrder.Dsc): q = q.OrderByDescending(a => a.Size); break; } await foreach (var r in q.Skip(request.Page * request.PageSize).Take(request.PageSize).AsAsyncEnumerable()) { yield return r; } } return new() { TotalResults = count, PageSize = request.PageSize, Page = request.Page, Results = Enumerate() }; } /// public async ValueTask Stats() { var size = await _db.Files .AsNoTracking() .SumAsync(a => (long)a.Size); var count = await _db.Files.CountAsync(); return new(count, (ulong)size); } }