using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Errors; using ErsatzTV.Core.Interfaces.Search; using ErsatzTV.Core.Search; using ErsatzTV.Infrastructure.Data; using ErsatzTV.Infrastructure.Extensions; using Microsoft.EntityFrameworkCore; namespace ErsatzTV.Application.MediaCollections; public class DeleteSmartCollectionHandler : IRequestHandler> { private readonly IDbContextFactory _dbContextFactory; private readonly ISearchTargets _searchTargets; private readonly ISmartCollectionCache _smartCollectionCache; public DeleteSmartCollectionHandler( IDbContextFactory dbContextFactory, ISearchTargets searchTargets, ISmartCollectionCache smartCollectionCache) { _dbContextFactory = dbContextFactory; _searchTargets = searchTargets; _smartCollectionCache = smartCollectionCache; } public async Task> Handle( DeleteSmartCollection request, CancellationToken cancellationToken) { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken); Option maybeSmartCollection = await SmartCollectionMustExist( dbContext, request, cancellationToken); return await maybeSmartCollection.Match( Some: smartCollection => DoDeletion(dbContext, smartCollection, cancellationToken).Map(Right), None: () => Task.FromResult>( new NotFoundError($"SmartCollection {request.SmartCollectionId} does not exist."))); } private async Task DoDeletion( TvContext dbContext, SmartCollection smartCollection, CancellationToken cancellationToken) { dbContext.SmartCollections.Remove(smartCollection); await dbContext.SaveChangesAsync(cancellationToken); _searchTargets.SearchTargetsChanged(); // post-commit side effect runs on CancellationToken.None so a late request cancellation // can't abort it after the commit landed (#254) await _smartCollectionCache.Refresh(CancellationToken.None); return Unit.Default; } private static Task> SmartCollectionMustExist( TvContext dbContext, DeleteSmartCollection request, CancellationToken cancellationToken) => dbContext.SmartCollections .SelectOneAsync(c => c.Id, c => c.Id == request.SmartCollectionId, cancellationToken) .Map(identity); }