using ErsatzTV.Application.Emby; using ErsatzTV.Application.Jellyfin; using ErsatzTV.Application.Plex; using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Locking; using ErsatzTV.Infrastructure.Data; using ErsatzTV.Infrastructure.Extensions; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace ErsatzTV.Application.Libraries; public class QueueShowScanByLibraryIdHandler( IDbContextFactory dbContextFactory, IEntityLocker locker, IMediator mediator, ILogger logger) : IRequestHandler { public async Task Handle(QueueShowScanByLibraryId request, CancellationToken cancellationToken) { await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); Option maybeLibrary = await dbContext.Libraries .AsNoTracking() .SelectOneAsync(l => l.Id, l => l.Id == request.LibraryId); foreach (Library library in maybeLibrary) { bool shouldSyncItems = library switch { PlexLibrary plexLibrary => plexLibrary.ShouldSyncItems, JellyfinLibrary jellyfinLibrary => jellyfinLibrary.ShouldSyncItems, EmbyLibrary embyLibrary => embyLibrary.ShouldSyncItems, _ => true }; if (!shouldSyncItems) { logger.LogWarning("Library sync is disabled for library id {Id}", library.Id); return false; } // Check if library is already being scanned - return false if locked if (!locker.LockLibrary(library.Id)) { logger.LogWarning("Library {Id} is already being scanned, cannot scan individual show", library.Id); return false; } logger.LogDebug( "Queued show scan for library id {Id}, show: {ShowTitle}, deepScan: {DeepScan}", library.Id, request.ShowTitle, request.DeepScan); try { switch (library) { case PlexLibrary: Either plexResult = await mediator.Send( new SynchronizePlexShowById(library.Id, request.ShowId, request.DeepScan), cancellationToken); return plexResult.IsRight; case JellyfinLibrary: Either jellyfinResult = await mediator.Send( new SynchronizeJellyfinShowById(library.Id, request.ShowId, request.DeepScan), cancellationToken); return jellyfinResult.IsRight; case EmbyLibrary: Either embyResult = await mediator.Send( new SynchronizeEmbyShowById(library.Id, request.ShowId, request.DeepScan), cancellationToken); return embyResult.IsRight; case LocalLibrary: logger.LogWarning("Single show scanning is not supported for local libraries"); return false; default: logger.LogWarning("Unknown library type for library {Id}", library.Id); return false; } } finally { // Always unlock the library when we're done locker.UnlockLibrary(library.Id); } } return false; } }