diff --git a/ErsatzTV.Core/Metadata/LocalSubtitlesProvider.cs b/ErsatzTV.Core/Metadata/LocalSubtitlesProvider.cs index 9bbabaa9..8479b1c2 100644 --- a/ErsatzTV.Core/Metadata/LocalSubtitlesProvider.cs +++ b/ErsatzTV.Core/Metadata/LocalSubtitlesProvider.cs @@ -59,6 +59,14 @@ public class LocalSubtitlesProvider : ILocalSubtitlesProvider _ => None }; + if (maybeMetadata.IsNone) + { + _logger.LogError( + "Failed to update subtitles; unable to load metadata for media item type {Type}", + mediaItem + .GetType().Name); + } + foreach (Domain.Metadata metadata in maybeMetadata) { MediaVersion version = mediaItem.GetHeadVersion(); @@ -69,7 +77,13 @@ public class LocalSubtitlesProvider : ILocalSubtitlesProvider var subtitles = subtitleStreams.Map(Subtitle.FromMediaStream).ToList(); string mediaItemPath = await localPath.IfNoneAsync(() => mediaItem.GetHeadVersion().MediaFiles.Head().Path); subtitles.AddRange(LocateExternalSubtitles(_languageCodes, mediaItemPath, saveFullPath)); - return await _metadataRepository.UpdateSubtitles(metadata, subtitles); + bool updateResult = await _metadataRepository.UpdateSubtitles(metadata, subtitles); + if (!updateResult) + { + _logger.LogError("Failed to save {Count} subtitles to database", subtitles.Count); + } + + return updateResult; } return false; diff --git a/ErsatzTV.Core/Metadata/MediaServerMovieLibraryScanner.cs b/ErsatzTV.Core/Metadata/MediaServerMovieLibraryScanner.cs index 1dc93695..d454f4f0 100644 --- a/ErsatzTV.Core/Metadata/MediaServerMovieLibraryScanner.cs +++ b/ErsatzTV.Core/Metadata/MediaServerMovieLibraryScanner.cs @@ -1,4 +1,5 @@ -using ErsatzTV.Core.Domain; +using System.Collections.Immutable; +using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain.MediaServer; using ErsatzTV.Core.Errors; using ErsatzTV.Core.Interfaces.Metadata; @@ -104,7 +105,8 @@ public abstract class MediaServerMovieLibraryScanner(); - List existingMovies = await movieRepository.GetExistingMovies(library); + IReadOnlyDictionary existingMovies = (await movieRepository.GetExistingMovies(library)) + .ToImmutableDictionary(e => e.MediaServerItemId, e => e); await foreach (TMovie incoming in movieEntries.WithCancellation(cancellationToken)) { @@ -181,7 +183,7 @@ public abstract class MediaServerMovieLibraryScanner m.MediaServerItemId).Except(incomingItemIds).ToList(); + var fileNotFoundItemIds = existingMovies.Keys.Except(incomingItemIds).ToList(); List ids = await movieRepository.FlagFileNotFound(library, fileNotFoundItemIds); await _searchIndex.RebuildItems(_searchRepository, _fallbackMetadataProvider, ids); @@ -215,7 +217,7 @@ public abstract class MediaServerMovieLibraryScanner ShouldScanItem( IMediaServerMovieRepository movieRepository, TLibrary library, - List existingMovies, + IReadOnlyDictionary existingMovies, TMovie incoming, string localPath, bool deepScan) @@ -226,10 +228,13 @@ public abstract class MediaServerMovieLibraryScanner maybeExisting = - existingMovies.Find(m => m.MediaServerItemId == MediaServerItemId(incoming)); - string existingEtag = await maybeExisting.Map(e => e.Etag ?? string.Empty).IfNoneAsync(string.Empty); - MediaItemState existingState = await maybeExisting.Map(e => e.State).IfNoneAsync(MediaItemState.Normal); + string existingEtag = string.Empty; + MediaItemState existingState = MediaItemState.Normal; + if (existingMovies.TryGetValue(MediaServerItemId(incoming), out TEtag existingEntry)) + { + existingEtag = existingEntry.Etag; + existingState = existingEntry.State; + } if (existingState is MediaItemState.Unavailable or MediaItemState.FileNotFound && existingEtag == MediaServerEtag(incoming)) @@ -255,7 +260,7 @@ public abstract class MediaServerMovieLibraryScanner