From 727a978689dc2f64c4be97734d15aa3e0df50fb1 Mon Sep 17 00:00:00 2001 From: Jason Dove <1695733+jasongdove@users.noreply.github.com> Date: Wed, 29 Oct 2025 14:01:14 -0500 Subject: [PATCH] fix block history and smart_collection search bugs (#2579) * fix block history when using mirror offset * fix smart_collection search crashes --- CHANGELOG.md | 3 +++ .../Playouts/Commands/BuildPlayoutHandler.cs | 4 ++-- .../Scheduling/BlockScheduling/BlockPlayoutBuilder.cs | 2 +- .../Scheduling/ChronologicalMediaCollectionEnumerator.cs | 9 +++++++-- ErsatzTV.Infrastructure/Search/SearchQueryParser.cs | 9 ++++++++- ErsatzTV/Pages/Playouts.razor | 2 +- 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87618223b..b3cddaf0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Fixed - Fix HLS Direct playback with Jellyfin 10.11 - Fix remote stream scripts (parsing issue with spaces and quotes) +- Fix block history being removed when it is still needed for mirror channel + - This caused playout build errors like "Unable to locate history for playout item" +- Fix crashes due to invalid smart collection searches, e.g. `smart_collection:"this collection does not exist"` ## [25.8.0] - 2025-10-26 ### Added diff --git a/ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs b/ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs index ec4d86a64..f6ea6b8db 100644 --- a/ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs +++ b/ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs @@ -367,8 +367,8 @@ public class BuildPlayoutHandler : IRequestHandler allItemsToDelete = referenceData.PlayoutHistory .GroupBy(h => h.Key) .SelectMany(group => group - .Filter(h => h.Finish < start.UtcDateTime) + .Filter(h => h.Finish < start.UtcDateTime - referenceData.MaxPlayoutOffset) .OrderByDescending(h => h.Finish) .Tail()); diff --git a/ErsatzTV.Core/Scheduling/ChronologicalMediaCollectionEnumerator.cs b/ErsatzTV.Core/Scheduling/ChronologicalMediaCollectionEnumerator.cs index 2343185fb..b7931b1b1 100644 --- a/ErsatzTV.Core/Scheduling/ChronologicalMediaCollectionEnumerator.cs +++ b/ErsatzTV.Core/Scheduling/ChronologicalMediaCollectionEnumerator.cs @@ -45,8 +45,13 @@ public sealed class ChronologicalMediaCollectionEnumerator : IMediaCollectionEnu public Option Current => _sortedMediaItems.Count != 0 ? _sortedMediaItems[State.Index] : None; public Option CurrentIncludeInProgramGuide { get; } - public void MoveNext(Option scheduledAt) => - State.Index = (State.Index + 1) % _sortedMediaItems.Count; + public void MoveNext(Option scheduledAt) + { + if (_sortedMediaItems.Count > 0) + { + State.Index = (State.Index + 1) % _sortedMediaItems.Count; + } + } public Option MinimumDuration => _lazyMinimumDuration.Value; diff --git a/ErsatzTV.Infrastructure/Search/SearchQueryParser.cs b/ErsatzTV.Infrastructure/Search/SearchQueryParser.cs index 6ad9f98b1..d9c9730c6 100644 --- a/ErsatzTV.Infrastructure/Search/SearchQueryParser.cs +++ b/ErsatzTV.Infrastructure/Search/SearchQueryParser.cs @@ -77,7 +77,8 @@ public partial class SearchQueryParser(ISmartCollectionCache smartCollectionCach if (parsedQuery == replaceResult.Query) { logger.LogWarning( - "Failed to replace smart_collection in query; is the syntax correct? Quotes are required. Giving up..."); + "Failed to replace smart_collection in query; is the syntax correct? Quotes are required. Giving up on collection {Name}...", + smartCollectionName); break; } @@ -125,6 +126,12 @@ public partial class SearchQueryParser(ISmartCollectionCache smartCollectionCach { result = result.Replace(match.Value, $"({smartCollectionQuery})"); } + + if (maybeQuery.IsNone) + { + //logger.LogError("Cannot find nested smart collection {Name}; removing from query.", smartCollectionName); + result = result.Replace(match.Value, "(type:bad_query)"); + } } return new ReplaceResult(result, false); diff --git a/ErsatzTV/Pages/Playouts.razor b/ErsatzTV/Pages/Playouts.razor index bbd836e80..33ceffd06 100644 --- a/ErsatzTV/Pages/Playouts.razor +++ b/ErsatzTV/Pages/Playouts.razor @@ -366,7 +366,7 @@ ? playout.PlayoutId : null; - _buildMessage = !playout.BuildStatus.Success && !string.IsNullOrWhiteSpace(playout.BuildStatus.Message) + _buildMessage = !(playout.BuildStatus?.Success ?? false) && !string.IsNullOrWhiteSpace(playout.BuildStatus?.Message) ? playout.BuildStatus.Message : string.Empty;