diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs index 34984daf2..a7e411200 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs @@ -37,6 +37,24 @@ namespace ErsatzTV.Core.Tests.Scheduling _logger = factory.CreateLogger(); } + [Test] + [Timeout(2000)] + public async Task ZeroDurationItem_Should_Abort() + { + var mediaItems = new List + { + TestMovie(1, TimeSpan.Zero, DateTime.Today) + }; + + (PlayoutBuilder builder, Playout playout) = TestDataFloodForItems(mediaItems, PlaybackOrder.Random); + DateTimeOffset start = HoursAfterMidnight(0); + DateTimeOffset finish = start + TimeSpan.FromHours(6); + + Playout result = await builder.BuildPlayoutItems(playout, start, finish); + + result.Items.Should().BeNull(); + } + [Test] public async Task InitialFlood_Should_StartAtMidnight() { diff --git a/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs b/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs index 1de8524f4..71951d160 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs @@ -88,6 +88,25 @@ namespace ErsatzTV.Core.Scheduling return playout; } + Option zeroDurationCollection = collectionMediaItems.Find( + c => c.Value.Any( + mi => mi switch + { + Movie m => m.MediaVersions.HeadOrNone().Map(mv => mv.Duration).IfNone(TimeSpan.Zero) == + TimeSpan.Zero, + Episode e => e.MediaVersions.HeadOrNone().Map(mv => mv.Duration).IfNone(TimeSpan.Zero) == + TimeSpan.Zero, + _ => true + })).Map(c => c.Key); + if (zeroDurationCollection.IsSome) + { + _logger.LogError( + "Unable to rebuild playout; collection {@CollectionKey} contains items with zero duration!", + zeroDurationCollection.ValueUnsafe()); + + return playout; + } + playout.Items ??= new List(); playout.ProgramScheduleAnchors ??= new List(); diff --git a/ErsatzTV/Services/SchedulerService.cs b/ErsatzTV/Services/SchedulerService.cs index 2653109d4..2a5d94c4b 100644 --- a/ErsatzTV/Services/SchedulerService.cs +++ b/ErsatzTV/Services/SchedulerService.cs @@ -56,7 +56,6 @@ namespace ErsatzTV.Services await ScanLocalMediaSources(cancellationToken); } - private async Task BuildPlayouts(CancellationToken cancellationToken) { using IServiceScope scope = _serviceScopeFactory.CreateScope();