Browse Source

reduce playout log spam (#2543)

pull/2544/head
Jason Dove 7 months ago committed by GitHub
parent
commit
ba5a027525
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 30
      ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs
  3. 32
      ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs
  4. 20
      ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerDurationTests.cs
  5. 26
      ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerFloodTests.cs
  6. 20
      ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerMultipleTests.cs
  7. 20
      ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerOneTests.cs
  8. 2
      ErsatzTV.Core/Interfaces/Scheduling/IPlayoutModeScheduler.cs
  9. 2
      ErsatzTV.Core/Scheduling/PlayoutBuildResult.cs
  10. 15
      ErsatzTV.Core/Scheduling/PlayoutBuildWarnings.cs
  11. 7
      ErsatzTV.Core/Scheduling/PlayoutBuilder.cs
  12. 51
      ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs
  13. 16
      ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs
  14. 15
      ErsatzTV.Core/Scheduling/PlayoutModeSchedulerFlood.cs
  15. 21
      ErsatzTV.Core/Scheduling/PlayoutModeSchedulerMultiple.cs
  16. 17
      ErsatzTV.Core/Scheduling/PlayoutModeSchedulerOne.cs
  17. 8
      ErsatzTV.Core/Scheduling/PlayoutSchedulerResult.cs

1
CHANGELOG.md

@ -40,6 +40,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -40,6 +40,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Changed
- Do not use graphics engine for single, permanent watermark
- Rename `YAML Validation` tool to `Sequential Schedule Validation`
- Greatly reduce debug log spam during playout builds by logging summaries of certain warnings at the end
## [25.7.1] - 2025-10-09
### Added

30
ErsatzTV.Application/Playouts/Commands/BuildPlayoutHandler.cs

@ -13,6 +13,7 @@ using ErsatzTV.Core.Scheduling; @@ -13,6 +13,7 @@ using ErsatzTV.Core.Scheduling;
using ErsatzTV.Infrastructure.Data;
using ErsatzTV.Infrastructure.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Channel = ErsatzTV.Core.Domain.Channel;
namespace ErsatzTV.Application.Playouts;
@ -29,6 +30,7 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro @@ -29,6 +30,7 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro
private readonly IPlayoutBuilder _playoutBuilder;
private readonly IPlayoutTimeShifter _playoutTimeShifter;
private readonly ChannelWriter<IBackgroundServiceRequest> _workerChannel;
private readonly ILogger<BuildPlayoutHandler> _logger;
private readonly ISequentialPlayoutBuilder _sequentialPlayoutBuilder;
private readonly IScriptedPlayoutBuilder _scriptedPlayoutBuilder;
@ -44,7 +46,8 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro @@ -44,7 +46,8 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro
IFFmpegSegmenterService ffmpegSegmenterService,
IEntityLocker entityLocker,
IPlayoutTimeShifter playoutTimeShifter,
ChannelWriter<IBackgroundServiceRequest> workerChannel)
ChannelWriter<IBackgroundServiceRequest> workerChannel,
ILogger<BuildPlayoutHandler> logger)
{
_client = client;
_dbContextFactory = dbContextFactory;
@ -58,6 +61,7 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro @@ -58,6 +61,7 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro
_entityLocker = entityLocker;
_playoutTimeShifter = playoutTimeShifter;
_workerChannel = workerChannel;
_logger = logger;
}
public async Task<Either<BaseError, Unit>> Handle(BuildPlayout request, CancellationToken cancellationToken)
@ -88,6 +92,30 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro @@ -88,6 +92,30 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro
{
await _playoutTimeShifter.TimeShift(request.PlayoutId, timeShiftTo, false, cancellationToken);
}
if (playoutBuildResult.Warnings.TailFillerTooLong > 0)
{
_logger.LogDebug(
"Playout {PlayoutId} skipped {Count} tail filler items that were too long to fit",
request.PlayoutId,
playoutBuildResult.Warnings.TailFillerTooLong);
}
if (playoutBuildResult.Warnings.MidRollContentWithoutChapters > 0)
{
_logger.LogDebug(
"Playout {PlayoutId} converted mid-roll to post-roll for {Count} items that have no chapter markers",
request.PlayoutId,
playoutBuildResult.Warnings.MidRollContentWithoutChapters);
}
if (playoutBuildResult.Warnings.DurationFillerSkipped > 0)
{
_logger.LogDebug(
"Playout {PlayoutId} skipped {Count} filler items to try to fit in a small remaining duration",
request.PlayoutId,
playoutBuildResult.Warnings.DurationFillerSkipped);
}
}
return result.Map(_ => Unit.Default);

32
ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs

@ -59,7 +59,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase @@ -59,7 +59,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase
scheduleItem,
new PlayoutItem(),
new List<MediaChapter>(),
true,
new PlayoutBuildWarnings(),
_cancellationToken);
playoutItems.Count.ShouldBe(1);
@ -112,7 +112,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase @@ -112,7 +112,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase
scheduleItem,
new PlayoutItem(),
new List<MediaChapter> { new() },
true,
new PlayoutBuildWarnings(),
_cancellationToken);
playoutItems.Count.ShouldBe(1);
@ -179,7 +179,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase @@ -179,7 +179,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase
new() { StartTime = TimeSpan.Zero, EndTime = TimeSpan.FromMinutes(6) },
new() { StartTime = TimeSpan.FromMinutes(6), EndTime = TimeSpan.FromMinutes(60) }
},
true,
new PlayoutBuildWarnings(),
_cancellationToken);
playoutItems.Count.ShouldBe(3);
@ -271,7 +271,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase @@ -271,7 +271,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase
new() { StartTime = TimeSpan.Zero, EndTime = TimeSpan.FromMinutes(6) },
new() { StartTime = TimeSpan.FromMinutes(6), EndTime = TimeSpan.FromMinutes(45) }
},
true,
new PlayoutBuildWarnings(),
_cancellationToken);
playoutItems.Count.ShouldBe(5);
@ -379,7 +379,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase @@ -379,7 +379,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase
new MediaChapter { StartTime = TimeSpan.FromMinutes(6), EndTime = TimeSpan.FromMinutes(30) },
new MediaChapter { StartTime = TimeSpan.FromMinutes(30), EndTime = TimeSpan.FromMinutes(45) }
],
true,
new PlayoutBuildWarnings(),
_cancellationToken);
playoutItems.Count.ShouldBe(5);
@ -488,7 +488,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase @@ -488,7 +488,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase
new MediaChapter { StartTime = TimeSpan.FromMinutes(20), EndTime = TimeSpan.FromMinutes(30) },
new MediaChapter { StartTime = TimeSpan.FromMinutes(30), EndTime = TimeSpan.FromMinutes(45) }
],
true,
new PlayoutBuildWarnings(),
_cancellationToken);
playoutItems.Count.ShouldBe(6);
@ -598,7 +598,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase @@ -598,7 +598,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase
new() { StartTime = TimeSpan.Zero, EndTime = TimeSpan.FromMinutes(6) },
new() { StartTime = TimeSpan.FromMinutes(6), EndTime = TimeSpan.FromMinutes(45) }
},
true,
new PlayoutBuildWarnings(),
_cancellationToken);
playoutItems.Count.ShouldBe(5);
@ -706,7 +706,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase @@ -706,7 +706,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase
new MediaChapter { StartTime = TimeSpan.FromMinutes(6), EndTime = TimeSpan.FromMinutes(30) },
new MediaChapter { StartTime = TimeSpan.FromMinutes(30), EndTime = TimeSpan.FromMinutes(45) }
],
true,
new PlayoutBuildWarnings(),
_cancellationToken);
playoutItems.Count.ShouldBe(5);
@ -770,15 +770,13 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase @@ -770,15 +770,13 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase
new()
{
Id = id,
MovieMetadata = new List<MovieMetadata> { new() { ReleaseDate = aired } },
MediaVersions = new List<MediaVersion>
{
new() { Duration = duration }
}
MovieMetadata = [new MovieMetadata { ReleaseDate = aired }],
MediaVersions = [new MediaVersion { Duration = duration }]
};
private class TestScheduler : PlayoutModeSchedulerBase<ProgramScheduleItem>
private class TestScheduler()
: PlayoutModeSchedulerBase<ProgramScheduleItem>(LoggerFactory.CreateLogger<TestScheduler>())
{
private static readonly ILoggerFactory LoggerFactory;
@ -792,11 +790,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase @@ -792,11 +790,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase
LoggerFactory = new LoggerFactory().AddSerilog(Log.Logger);
}
public TestScheduler() : base(LoggerFactory.CreateLogger<TestScheduler>())
{
}
public override Tuple<PlayoutBuilderState, List<PlayoutItem>> Schedule(
public override PlayoutSchedulerResult Schedule(
PlayoutBuilderState playoutBuilderState,
Dictionary<CollectionKey, IMediaCollectionEnumerator> collectionEnumerators,
ProgramScheduleItem scheduleItem,

20
ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerDurationTests.cs

@ -60,7 +60,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase @@ -60,7 +60,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerDuration(_logger);
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -133,7 +133,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase @@ -133,7 +133,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerDuration(_logger);
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -205,7 +205,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase @@ -205,7 +205,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerDuration(_logger);
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -274,7 +274,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase @@ -274,7 +274,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerDuration(_logger);
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -357,7 +357,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase @@ -357,7 +357,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerDuration(_logger);
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.FallbackFiller, enumerator2),
scheduleItem,
@ -444,7 +444,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase @@ -444,7 +444,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerDuration(_logger);
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.TailFiller, enumerator2),
scheduleItem,
@ -543,7 +543,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase @@ -543,7 +543,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerDuration(_logger);
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.TailFiller, enumerator2),
scheduleItem,
@ -653,7 +653,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase @@ -653,7 +653,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerDuration(_logger);
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -802,7 +802,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase @@ -802,7 +802,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerDuration(_logger);
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -874,7 +874,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase @@ -874,7 +874,7 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerDuration(_logger);
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,

26
ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerFloodTests.cs

@ -51,7 +51,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -51,7 +51,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerFlood(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -126,7 +126,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -126,7 +126,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerFlood(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -223,7 +223,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -223,7 +223,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerFlood(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -308,7 +308,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -308,7 +308,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerFlood(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.PostRollFiller, enumerator2),
scheduleItem,
@ -396,7 +396,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -396,7 +396,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerFlood(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -478,7 +478,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -478,7 +478,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerFlood(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.TailFiller, enumerator2),
scheduleItem,
@ -576,7 +576,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -576,7 +576,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerFlood(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.FallbackFiller, enumerator2),
scheduleItem,
@ -664,7 +664,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -664,7 +664,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerFlood(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.TailFiller, enumerator2),
scheduleItem,
@ -772,7 +772,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -772,7 +772,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerFlood(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -886,7 +886,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -886,7 +886,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
// hard stop at 2, an hour before the "next schedule item" at 3
DateTimeOffset hardStop = StartState(scheduleItemsEnumerator).CurrentTime.AddHours(2);
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -992,7 +992,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -992,7 +992,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
// hard stop at 2, an hour before the "next schedule item" at 3
DateTimeOffset hardStop = StartState(scheduleItemsEnumerator).CurrentTime.AddHours(2);
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -1104,7 +1104,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -1104,7 +1104,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerFlood(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -1184,7 +1184,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase @@ -1184,7 +1184,7 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerFlood(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,

20
ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerMultipleTests.cs

@ -53,7 +53,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase @@ -53,7 +53,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -155,7 +155,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase @@ -155,7 +155,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -226,7 +226,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase @@ -226,7 +226,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -301,7 +301,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase @@ -301,7 +301,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -384,7 +384,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase @@ -384,7 +384,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.TailFiller, enumerator2),
scheduleItem,
@ -483,7 +483,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase @@ -483,7 +483,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.FallbackFiller, enumerator2),
scheduleItem,
@ -572,7 +572,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase @@ -572,7 +572,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.TailFiller, enumerator2),
scheduleItem,
@ -682,7 +682,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase @@ -682,7 +682,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -804,7 +804,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase @@ -804,7 +804,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -890,7 +890,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase @@ -890,7 +890,7 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerMultiple(collectionItemCount, Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,

20
ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerOneTests.cs

@ -45,7 +45,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase @@ -45,7 +45,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerOne(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,
@ -122,7 +122,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase @@ -122,7 +122,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerOne(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -196,7 +196,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase @@ -196,7 +196,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerOne(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.TailFiller, enumerator2),
scheduleItem,
@ -278,7 +278,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase @@ -278,7 +278,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerOne(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.FallbackFiller, enumerator2),
scheduleItem,
@ -350,7 +350,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase @@ -350,7 +350,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerOne(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator1, scheduleItem.TailFiller, enumerator2),
scheduleItem,
@ -442,7 +442,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase @@ -442,7 +442,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerOne(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -546,7 +546,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase @@ -546,7 +546,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerOne(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -632,7 +632,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase @@ -632,7 +632,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerOne(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -732,7 +732,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase @@ -732,7 +732,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerOne(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(
scheduleItem,
@ -817,7 +817,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase @@ -817,7 +817,7 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
var scheduler = new PlayoutModeSchedulerOne(Substitute.For<ILogger>());
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems) = scheduler.Schedule(
(PlayoutBuilderState playoutBuilderState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings _) = scheduler.Schedule(
startState,
CollectionEnumerators(scheduleItem, enumerator),
scheduleItem,

2
ErsatzTV.Core/Interfaces/Scheduling/IPlayoutModeScheduler.cs

@ -5,7 +5,7 @@ namespace ErsatzTV.Core.Interfaces.Scheduling; @@ -5,7 +5,7 @@ namespace ErsatzTV.Core.Interfaces.Scheduling;
public interface IPlayoutModeScheduler<in T> where T : ProgramScheduleItem
{
Tuple<PlayoutBuilderState, List<PlayoutItem>> Schedule(
PlayoutSchedulerResult Schedule(
PlayoutBuilderState playoutBuilderState,
Dictionary<CollectionKey, IMediaCollectionEnumerator> collectionEnumerators,
T scheduleItem,

2
ErsatzTV.Core/Scheduling/PlayoutBuildResult.cs

@ -27,4 +27,6 @@ public record PlayoutBuildResult( @@ -27,4 +27,6 @@ public record PlayoutBuildResult(
[],
[],
Option<DateTimeOffset>.None);
public PlayoutBuildWarnings Warnings { get; } = new();
}

15
ErsatzTV.Core/Scheduling/PlayoutBuildWarnings.cs

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
namespace ErsatzTV.Core.Scheduling;
public class PlayoutBuildWarnings
{
public void Merge(PlayoutBuildWarnings warnings)
{
TailFillerTooLong += warnings.TailFillerTooLong;
MidRollContentWithoutChapters += warnings.MidRollContentWithoutChapters;
DurationFillerSkipped += warnings.DurationFillerSkipped;
}
public int TailFillerTooLong { get; set; }
public int MidRollContentWithoutChapters { get; set; }
public int DurationFillerSkipped { get; set; }
}

7
ErsatzTV.Core/Scheduling/PlayoutBuilder.cs

@ -818,7 +818,7 @@ public class PlayoutBuilder : IPlayoutBuilder @@ -818,7 +818,7 @@ public class PlayoutBuilder : IPlayoutBuilder
ProgramScheduleItem nextScheduleItem = playoutBuilderState.ScheduleItemsEnumerator.Peek(1);
Tuple<PlayoutBuilderState, List<PlayoutItem>> schedulerResult = scheduleItem switch
PlayoutSchedulerResult schedulerResult = scheduleItem switch
{
ProgramScheduleItemMultiple multiple => schedulerMultiple.Schedule(
playoutBuilderState,
@ -851,7 +851,10 @@ public class PlayoutBuilder : IPlayoutBuilder @@ -851,7 +851,10 @@ public class PlayoutBuilder : IPlayoutBuilder
_ => throw new NotSupportedException(nameof(scheduleItem))
};
(PlayoutBuilderState nextState, List<PlayoutItem> playoutItems) = schedulerResult;
(PlayoutBuilderState nextState, List<PlayoutItem> playoutItems, PlayoutBuildWarnings warnings) =
schedulerResult;
result.Warnings.Merge(warnings);
// if we completed a multiple/duration block, move to the next fill group
if (scheduleItem.FillWithGroupMode is not FillWithGroupMode.None)

51
ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs

@ -10,14 +10,14 @@ using Microsoft.Extensions.Logging; @@ -10,14 +10,14 @@ using Microsoft.Extensions.Logging;
namespace ErsatzTV.Core.Scheduling;
[SuppressMessage("Design", "CA1000:Do not declare static members on generic types")]
public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> where T : ProgramScheduleItem
public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutModeScheduler<T>
where T : ProgramScheduleItem
{
private readonly Random _random = new();
protected PlayoutModeSchedulerBase(ILogger logger) => Logger = logger;
protected ILogger Logger { get; }
protected ILogger Logger { get; } = logger;
public abstract Tuple<PlayoutBuilderState, List<PlayoutItem>> Schedule(
public abstract PlayoutSchedulerResult Schedule(
PlayoutBuilderState playoutBuilderState,
Dictionary<CollectionKey, IMediaCollectionEnumerator> collectionEnumerators,
T scheduleItem,
@ -130,6 +130,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -130,6 +130,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
ProgramScheduleItem scheduleItem,
List<PlayoutItem> playoutItems,
DateTimeOffset nextItemStart,
PlayoutBuildWarnings warnings,
CancellationToken cancellationToken)
{
var newItems = new List<PlayoutItem>(playoutItems);
@ -149,11 +150,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -149,11 +150,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
if (nextState.CurrentTime + itemDuration > nextItemStart)
{
Logger.LogDebug(
"Filler with duration {Duration:hh\\:mm\\:ss} will go past next item start {NextItemStart}",
itemDuration,
nextItemStart);
warnings.TailFillerTooLong++;
break;
}
@ -275,7 +272,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -275,7 +272,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
ProgramScheduleItem scheduleItem,
PlayoutItem playoutItem,
List<MediaChapter> chapters,
bool log,
PlayoutBuildWarnings warnings,
CancellationToken cancellationToken)
{
var result = new List<PlayoutItem>();
@ -312,8 +309,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -312,8 +309,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
// convert mid-roll to post-roll if we have no chapters
if (allFiller.Any(f => f.FillerKind is FillerKind.MidRoll) && effectiveChapters.Count == 0)
{
Logger.LogInformation(
"Converting mid-roll filler preset to post-roll for content that has no chapter markers");
warnings.MidRollContentWithoutChapters++;
var toRemove = allFiller.Filter(f => f.FillerKind is FillerKind.MidRoll).ToList();
allFiller.RemoveAll(toRemove.Contains);
@ -403,8 +399,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -403,8 +399,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
filler.Duration.Value,
scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.PreRoll,
filler.AllowWatermarks,
log,
cancellationToken));
warnings));
break;
case FillerMode.Count when filler.Count.HasValue:
IMediaCollectionEnumerator e2 = enumerators[CollectionKey.ForFillerPreset(filler)];
@ -468,8 +463,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -468,8 +463,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
? FillerKind.GuideMode
: FillerKind.MidRoll,
filler.AllowWatermarks,
log,
cancellationToken));
warnings));
}
}
@ -534,8 +528,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -534,8 +528,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
filler.Duration.Value,
scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.PostRoll,
filler.AllowWatermarks,
log,
cancellationToken));
warnings));
break;
case FillerMode.Count when filler.Count.HasValue:
IMediaCollectionEnumerator e2 = enumerators[CollectionKey.ForFillerPreset(filler)];
@ -628,8 +621,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -628,8 +621,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
remainingToFill,
scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.PreRoll,
padFiller.AllowWatermarks,
log,
cancellationToken));
warnings));
totalDuration = TimeSpan.FromTicks(result.Sum(pi => (pi.Finish - pi.Start).Ticks));
remainingToFill = targetTime - totalDuration - playoutItem.StartOffset;
if (remainingToFill > TimeSpan.Zero)
@ -654,8 +646,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -654,8 +646,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
remainingToFill,
scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.MidRoll,
padFiller.AllowWatermarks,
log,
cancellationToken));
warnings));
TimeSpan average = filteredChapters.Count <= 1
? remainingToFill
: remainingToFill / (filteredChapters.Count - 1);
@ -718,8 +709,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -718,8 +709,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
remainingToFill,
scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.PostRoll,
padFiller.AllowWatermarks,
log,
cancellationToken));
warnings));
totalDuration = TimeSpan.FromTicks(result.Sum(pi => (pi.Finish - pi.Start).Ticks));
remainingToFill = targetTime - totalDuration - playoutItem.StartOffset;
if (remainingToFill > TimeSpan.Zero)
@ -792,14 +782,13 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -792,14 +782,13 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
return result;
}
private List<PlayoutItem> AddDurationFiller(
private static List<PlayoutItem> AddDurationFiller(
PlayoutBuilderState playoutBuilderState,
IMediaCollectionEnumerator enumerator,
TimeSpan duration,
FillerKind fillerKind,
bool allowWatermarks,
bool log,
CancellationToken cancellationToken)
PlayoutBuildWarnings warnings)
{
var result = new List<PlayoutItem>();
@ -836,13 +825,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -836,13 +825,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
}
else
{
if (log)
{
Logger.LogDebug(
"Filler item is too long {FillerDuration:g} to fill {GapDuration:g}; skipping to next filler item",
itemDuration,
remainingToFill);
}
warnings.DurationFillerSkipped++;
// TODO: this won't work with reruns
enumerator.MoveNext(Option<DateTimeOffset>.None);

16
ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs

@ -7,13 +7,10 @@ using Microsoft.Extensions.Logging; @@ -7,13 +7,10 @@ using Microsoft.Extensions.Logging;
namespace ErsatzTV.Core.Scheduling;
public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase<ProgramScheduleItemDuration>
public class PlayoutModeSchedulerDuration(ILogger logger)
: PlayoutModeSchedulerBase<ProgramScheduleItemDuration>(logger)
{
public PlayoutModeSchedulerDuration(ILogger logger) : base(logger)
{
}
public override Tuple<PlayoutBuilderState, List<PlayoutItem>> Schedule(
public override PlayoutSchedulerResult Schedule(
PlayoutBuilderState playoutBuilderState,
Dictionary<CollectionKey, IMediaCollectionEnumerator> collectionEnumerators,
ProgramScheduleItemDuration scheduleItem,
@ -21,6 +18,8 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase<ProgramSche @@ -21,6 +18,8 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase<ProgramSche
DateTimeOffset hardStop,
CancellationToken cancellationToken)
{
var warnings = new PlayoutBuildWarnings();
// Logger.LogDebug(
// "DurationSchedule: {ItemId} {CurrentTime} {DurationFinish} {InDurationFiller} {HardStop}",
// scheduleItem.Id,
@ -205,7 +204,7 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase<ProgramSche @@ -205,7 +204,7 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase<ProgramSche
scheduleItem,
playoutItem,
itemChapters,
false,
warnings,
cancellationToken);
// foreach (PlayoutItem pi in maybePlayoutItems.OrderBy(pi => pi.StartOffset))
@ -294,6 +293,7 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase<ProgramSche @@ -294,6 +293,7 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase<ProgramSche
scheduleItem,
playoutItems,
nextItemStart,
warnings,
cancellationToken);
}
@ -348,6 +348,6 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase<ProgramSche @@ -348,6 +348,6 @@ public class PlayoutModeSchedulerDuration : PlayoutModeSchedulerBase<ProgramSche
nextState = nextState with { NextGuideGroup = nextState.IncrementGuideGroup };
return Tuple(nextState, playoutItems);
return new PlayoutSchedulerResult(nextState, playoutItems, warnings);
}
}

15
ErsatzTV.Core/Scheduling/PlayoutModeSchedulerFlood.cs

@ -7,14 +7,9 @@ using Microsoft.Extensions.Logging; @@ -7,14 +7,9 @@ using Microsoft.Extensions.Logging;
namespace ErsatzTV.Core.Scheduling;
public class PlayoutModeSchedulerFlood : PlayoutModeSchedulerBase<ProgramScheduleItemFlood>
public class PlayoutModeSchedulerFlood(ILogger logger) : PlayoutModeSchedulerBase<ProgramScheduleItemFlood>(logger)
{
public PlayoutModeSchedulerFlood(ILogger logger)
: base(logger)
{
}
public override Tuple<PlayoutBuilderState, List<PlayoutItem>> Schedule(
public override PlayoutSchedulerResult Schedule(
PlayoutBuilderState playoutBuilderState,
Dictionary<CollectionKey, IMediaCollectionEnumerator> collectionEnumerators,
ProgramScheduleItemFlood scheduleItem,
@ -22,6 +17,7 @@ public class PlayoutModeSchedulerFlood : PlayoutModeSchedulerBase<ProgramSchedul @@ -22,6 +17,7 @@ public class PlayoutModeSchedulerFlood : PlayoutModeSchedulerBase<ProgramSchedul
DateTimeOffset hardStop,
CancellationToken cancellationToken)
{
var warnings = new PlayoutBuildWarnings();
var playoutItems = new List<PlayoutItem>();
PlayoutBuilderState nextState = playoutBuilderState;
@ -120,7 +116,7 @@ public class PlayoutModeSchedulerFlood : PlayoutModeSchedulerBase<ProgramSchedul @@ -120,7 +116,7 @@ public class PlayoutModeSchedulerFlood : PlayoutModeSchedulerBase<ProgramSchedul
scheduleItem,
playoutItem,
itemChapters,
false,
warnings,
cancellationToken);
DateTimeOffset itemEndTimeWithFiller = maybePlayoutItems.Max(pi => pi.FinishOffset);
@ -189,6 +185,7 @@ public class PlayoutModeSchedulerFlood : PlayoutModeSchedulerBase<ProgramSchedul @@ -189,6 +185,7 @@ public class PlayoutModeSchedulerFlood : PlayoutModeSchedulerBase<ProgramSchedul
scheduleItem,
playoutItems,
peekItemStart,
warnings,
cancellationToken);
}
@ -205,6 +202,6 @@ public class PlayoutModeSchedulerFlood : PlayoutModeSchedulerBase<ProgramSchedul @@ -205,6 +202,6 @@ public class PlayoutModeSchedulerFlood : PlayoutModeSchedulerBase<ProgramSchedul
nextState = nextState with { NextGuideGroup = nextState.IncrementGuideGroup };
return Tuple(nextState, playoutItems);
return new PlayoutSchedulerResult(nextState, playoutItems, warnings);
}
}

21
ErsatzTV.Core/Scheduling/PlayoutModeSchedulerMultiple.cs

@ -7,15 +7,10 @@ using Microsoft.Extensions.Logging; @@ -7,15 +7,10 @@ using Microsoft.Extensions.Logging;
namespace ErsatzTV.Core.Scheduling;
public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase<ProgramScheduleItemMultiple>
public class PlayoutModeSchedulerMultiple(Map<CollectionKey, int> collectionItemCount, ILogger logger)
: PlayoutModeSchedulerBase<ProgramScheduleItemMultiple>(logger)
{
private readonly Map<CollectionKey, int> _collectionItemCount;
public PlayoutModeSchedulerMultiple(Map<CollectionKey, int> collectionItemCount, ILogger logger)
: base(logger) =>
_collectionItemCount = collectionItemCount;
public override Tuple<PlayoutBuilderState, List<PlayoutItem>> Schedule(
public override PlayoutSchedulerResult Schedule(
PlayoutBuilderState playoutBuilderState,
Dictionary<CollectionKey, IMediaCollectionEnumerator> collectionEnumerators,
ProgramScheduleItemMultiple scheduleItem,
@ -23,13 +18,14 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase<ProgramSche @@ -23,13 +18,14 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase<ProgramSche
DateTimeOffset hardStop,
CancellationToken cancellationToken)
{
var warnings = new PlayoutBuildWarnings();
var playoutItems = new List<PlayoutItem>();
DateTimeOffset firstStart = GetStartTimeAfter(playoutBuilderState, scheduleItem, Option<ILogger>.Some(Logger));
if (firstStart >= hardStop)
{
playoutBuilderState = playoutBuilderState with { CurrentTime = hardStop };
return Tuple(playoutBuilderState, playoutItems);
return new PlayoutSchedulerResult(playoutBuilderState, playoutItems, warnings);
}
PlayoutBuilderState nextState = playoutBuilderState with
@ -48,7 +44,7 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase<ProgramSche @@ -48,7 +44,7 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase<ProgramSche
case MultipleMode.CollectionSize:
nextState = nextState with
{
MultipleRemaining = _collectionItemCount[CollectionKey.ForScheduleItem(scheduleItem)]
MultipleRemaining = collectionItemCount[CollectionKey.ForScheduleItem(scheduleItem)]
};
break;
case MultipleMode.PlaylistItemSize:
@ -143,7 +139,7 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase<ProgramSche @@ -143,7 +139,7 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase<ProgramSche
scheduleItem,
playoutItem,
itemChapters,
true,
warnings,
cancellationToken));
nextState = nextState with
@ -189,6 +185,7 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase<ProgramSche @@ -189,6 +185,7 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase<ProgramSche
scheduleItem,
playoutItems,
nextItemStart,
warnings,
cancellationToken);
}
@ -205,6 +202,6 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase<ProgramSche @@ -205,6 +202,6 @@ public class PlayoutModeSchedulerMultiple : PlayoutModeSchedulerBase<ProgramSche
nextState = nextState with { NextGuideGroup = nextState.IncrementGuideGroup };
return Tuple(nextState, playoutItems);
return new PlayoutSchedulerResult(nextState, playoutItems, warnings);
}
}

17
ErsatzTV.Core/Scheduling/PlayoutModeSchedulerOne.cs

@ -6,13 +6,9 @@ using Microsoft.Extensions.Logging; @@ -6,13 +6,9 @@ using Microsoft.Extensions.Logging;
namespace ErsatzTV.Core.Scheduling;
public class PlayoutModeSchedulerOne : PlayoutModeSchedulerBase<ProgramScheduleItemOne>
public class PlayoutModeSchedulerOne(ILogger logger) : PlayoutModeSchedulerBase<ProgramScheduleItemOne>(logger)
{
public PlayoutModeSchedulerOne(ILogger logger) : base(logger)
{
}
public override Tuple<PlayoutBuilderState, List<PlayoutItem>> Schedule(
public override PlayoutSchedulerResult Schedule(
PlayoutBuilderState playoutBuilderState,
Dictionary<CollectionKey, IMediaCollectionEnumerator> collectionEnumerators,
ProgramScheduleItemOne scheduleItem,
@ -20,6 +16,8 @@ public class PlayoutModeSchedulerOne : PlayoutModeSchedulerBase<ProgramScheduleI @@ -20,6 +16,8 @@ public class PlayoutModeSchedulerOne : PlayoutModeSchedulerBase<ProgramScheduleI
DateTimeOffset hardStop,
CancellationToken cancellationToken)
{
var warnings = new PlayoutBuildWarnings();
IMediaCollectionEnumerator contentEnumerator =
collectionEnumerators[CollectionKey.ForScheduleItem(scheduleItem)];
foreach (MediaItem mediaItem in contentEnumerator.Current)
@ -88,7 +86,7 @@ public class PlayoutModeSchedulerOne : PlayoutModeSchedulerBase<ProgramScheduleI @@ -88,7 +86,7 @@ public class PlayoutModeSchedulerOne : PlayoutModeSchedulerBase<ProgramScheduleI
scheduleItem,
playoutItem,
itemChapters,
true,
warnings,
cancellationToken);
PlayoutBuilderState nextState = playoutBuilderState with
@ -116,6 +114,7 @@ public class PlayoutModeSchedulerOne : PlayoutModeSchedulerBase<ProgramScheduleI @@ -116,6 +114,7 @@ public class PlayoutModeSchedulerOne : PlayoutModeSchedulerBase<ProgramScheduleI
scheduleItem,
playoutItems,
nextItemStart,
warnings,
cancellationToken);
}
@ -132,9 +131,9 @@ public class PlayoutModeSchedulerOne : PlayoutModeSchedulerBase<ProgramScheduleI @@ -132,9 +131,9 @@ public class PlayoutModeSchedulerOne : PlayoutModeSchedulerBase<ProgramScheduleI
nextState = nextState with { NextGuideGroup = nextState.IncrementGuideGroup };
return Tuple(nextState, playoutItems);
return new PlayoutSchedulerResult(nextState, playoutItems, warnings);
}
return Tuple(playoutBuilderState, new List<PlayoutItem>());
return new PlayoutSchedulerResult(playoutBuilderState, [], warnings);
}
}

8
ErsatzTV.Core/Scheduling/PlayoutSchedulerResult.cs

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
using ErsatzTV.Core.Domain;
namespace ErsatzTV.Core.Scheduling;
public record PlayoutSchedulerResult(
PlayoutBuilderState State,
List<PlayoutItem> PlayoutItems,
PlayoutBuildWarnings Warnings);
Loading…
Cancel
Save