Browse Source

skip zero duration items when building playouts (#236)

pull/237/head
Jason Dove 5 years ago committed by GitHub
parent
commit
eee10dee22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      CHANGELOG.md
  2. 23
      ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs
  3. 39
      ErsatzTV.Core/Scheduling/PlayoutBuilder.cs

8
CHANGELOG.md

@ -3,7 +3,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## Unreleased ## [Unreleased]
### Changed
- Skip zero duration items when building a playout, rather than aborting the playout build
### Fixed
- Fix edge case where a playout rebuild would get stuck and block all other playouts and library scans
## [0.0.41-prealpha] - 2021-05-30 ## [0.0.41-prealpha] - 2021-05-30
### Added ### Added

23
ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs

@ -39,7 +39,7 @@ namespace ErsatzTV.Core.Tests.Scheduling
[Test] [Test]
[Timeout(2000)] [Timeout(2000)]
public async Task ZeroDurationItem_Should_Abort() public async Task OnlyZeroDurationItem_Should_Abort()
{ {
var mediaItems = new List<MediaItem> var mediaItems = new List<MediaItem>
{ {
@ -55,6 +55,27 @@ namespace ErsatzTV.Core.Tests.Scheduling
result.Items.Should().BeNull(); result.Items.Should().BeNull();
} }
[Test]
public async Task ZeroDurationItem_Should_BeSkipped()
{
var mediaItems = new List<MediaItem>
{
TestMovie(1, TimeSpan.Zero, DateTime.Today),
TestMovie(2, TimeSpan.FromHours(6), 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.Count.Should().Be(1);
result.Items.Head().MediaItemId.Should().Be(2);
result.Items.Head().StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero);
result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6));
}
[Test] [Test]
public async Task InitialFlood_Should_StartAtMidnight() public async Task InitialFlood_Should_StartAtMidnight()
{ {

39
ErsatzTV.Core/Scheduling/PlayoutBuilder.cs

@ -80,17 +80,52 @@ namespace ErsatzTV.Core.Scheduling
playout.Channel.Number, playout.Channel.Number,
playout.Channel.Name); playout.Channel.Name);
foreach ((CollectionKey _, List<MediaItem> items) in collectionMediaItems)
{
var zeroItems = new List<MediaItem>();
foreach (MediaItem item in items)
{
bool isZero = item switch
{
Movie m => await m.MediaVersions.Map(v => v.Duration).HeadOrNone().IfNoneAsync(TimeSpan.Zero) ==
TimeSpan.Zero,
Episode e => await e.MediaVersions.Map(v => v.Duration).HeadOrNone()
.IfNoneAsync(TimeSpan.Zero) ==
TimeSpan.Zero,
MusicVideo mv => await mv.MediaVersions.Map(v => v.Duration).HeadOrNone()
.IfNoneAsync(TimeSpan.Zero) ==
TimeSpan.Zero,
_ => true
};
if (isZero)
{
_logger.LogWarning(
"Skipping media item with zero duration {MediaItem} - {MediaItemTitle}",
item.Id,
DisplayTitle(item));
zeroItems.Add(item);
}
}
items.RemoveAll(i => zeroItems.Contains(i));
}
// this guard needs to be below the place where we modify the collections (by removing zero-duration items)
Option<CollectionKey> emptyCollection = Option<CollectionKey> emptyCollection =
collectionMediaItems.Find(c => !c.Value.Any()).Map(c => c.Key); collectionMediaItems.Find(c => !c.Value.Any()).Map(c => c.Key);
if (emptyCollection.IsSome) if (emptyCollection.IsSome)
{ {
_logger.LogError( _logger.LogError(
"Unable to rebuild playout; collection {@CollectionKey} has no items!", "Unable to rebuild playout; collection {@CollectionKey} has no valid items!",
emptyCollection.ValueUnsafe()); emptyCollection.ValueUnsafe());
return playout; return playout;
} }
// leaving this guard in for a while to ensure the zero item removal is working properly
Option<CollectionKey> zeroDurationCollection = collectionMediaItems.Find( Option<CollectionKey> zeroDurationCollection = collectionMediaItems.Find(
c => c.Value.Any( c => c.Value.Any(
mi => mi switch mi => mi switch
@ -106,7 +141,7 @@ namespace ErsatzTV.Core.Scheduling
if (zeroDurationCollection.IsSome) if (zeroDurationCollection.IsSome)
{ {
_logger.LogError( _logger.LogError(
"Unable to rebuild playout; collection {@CollectionKey} contains items with zero duration!", "BUG: Unable to rebuild playout; collection {@CollectionKey} contains items with zero duration!",
zeroDurationCollection.ValueUnsafe()); zeroDurationCollection.ValueUnsafe());
return playout; return playout;

Loading…
Cancel
Save