Browse Source

fix: block scheduler deleting playout items (#2992)

pull/2994/head
Jason Dove 3 weeks ago committed by GitHub
parent
commit
b7aaea3d46
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      CHANGELOG.md
  2. 120
      ErsatzTV.Core.Tests/Scheduling/BlockScheduling/BlockPlayoutBuilderTests.cs
  3. 6
      ErsatzTV.Core/Scheduling/BlockScheduling/BlockPlayoutBuilder.cs

3
CHANGELOG.md

@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Fixed
- Fix block scheduler deleting the current hour's playout items, taking the channel offline until the next block
## [26.8.1] - 2026-08-29
### Security
- Fix GHSA-h3r4-r2f2-qf59 (CVE-PENDING)

120
ErsatzTV.Core.Tests/Scheduling/BlockScheduling/BlockPlayoutBuilderTests.cs

@ -638,6 +638,126 @@ public class BlockPlayoutBuilderTests @@ -638,6 +638,126 @@ public class BlockPlayoutBuilderTests
result.AddedItems[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(9));
}
}
[Test]
[CancelAfter(10_000)]
public async Task RemoveBefore_Must_Not_Move_Into_The_Future(CancellationToken cancellationToken)
{
var collection = new SmartCollection { Id = 1, Query = "asdf" };
var block = new Block
{
Id = 1,
Name = "Test Block",
Minutes = 50,
Items =
[
new BlockItem
{
Id = 1,
CollectionType = CollectionType.SmartCollection,
PlaybackOrder = PlaybackOrder.Chronological,
Index = 1,
SmartCollection = collection,
SmartCollectionId = collection.Id
}
],
StopScheduling = BlockStopScheduling.BeforeDurationEnd
};
var template = new Template { Id = 1, Items = [] };
template.Items.Add(
new TemplateItem
{
Block = block,
BlockId = block.Id,
StartTime = TimeSpan.FromHours(8),
Template = template,
TemplateId = template.Id
});
var playoutTemplate = new PlayoutTemplate
{
Id = 1,
Index = 1,
Template = template,
TemplateId = template.Id,
DaysOfMonth = AlternateScheduleSelector.AllDaysOfMonth(),
DaysOfWeek = AlternateScheduleSelector.AllDaysOfWeek(),
MonthsOfYear = AlternateScheduleSelector.AllMonthsOfYear()
};
var playout = new Playout
{
Id = 1,
Channel = new Channel(Guid.Empty) { Id = 1, Name = "Test Channel" },
Templates = [playoutTemplate],
Items = [],
PlayoutHistory = []
};
DateTimeOffset midnight = DateTimeOffset.Now - DateTimeOffset.Now.TimeOfDay;
DateTimeOffset now = midnight.AddHours(9);
var mediaItems = new List<MediaItem>
{
new Movie
{
Id = 1,
MovieMetadata = [new MovieMetadata { ReleaseDate = DateTime.Today }],
MediaVersions =
[
new MediaVersion
{
Duration = TimeSpan.FromMinutes(25),
MediaFiles = [new MediaFile { Path = "/fake/path/1" }]
}
]
}
};
var collectionRepo = new FakeMediaCollectionRepository(Map((collection.Id, mediaItems)));
IConfigElementRepository configRepo = Substitute.For<IConfigElementRepository>();
configRepo
.GetValue<int>(Arg.Is(ConfigElementKey.PlayoutDaysToBuild), Arg.Any<CancellationToken>())
.Returns(Some(1));
var builder = new BlockPlayoutBuilder(
configRepo,
collectionRepo,
Substitute.For<ITelevisionRepository>(),
Substitute.For<IArtistRepository>(),
Substitute.For<ICollectionEtag>(),
new LoggerFactory().CreateLogger<BlockPlayoutBuilder>());
var referenceData = new PlayoutReferenceData(
playout.Channel,
Option<Deco>.None,
[],
playout.Templates.ToList(),
null,
[],
[],
TimeSpan.Zero);
Either<BaseError, PlayoutBuildResult> buildResult = await builder.Build(
now,
playout,
referenceData,
PlayoutBuildMode.Continue,
cancellationToken);
buildResult.IsRight.ShouldBeTrue();
foreach (PlayoutBuildResult result in buildResult.RightToSeq())
{
DateTimeOffset removeBefore = result.RemoveBefore.IfNone(DateTimeOffset.MinValue);
await TestContext.Out.WriteLineAsync($"build start = {now:O}");
await TestContext.Out.WriteLineAsync($"RemoveBefore = {removeBefore:O}");
removeBefore.ShouldBeLessThanOrEqualTo(now);
}
}
}

6
ErsatzTV.Core/Scheduling/BlockScheduling/BlockPlayoutBuilder.cs

@ -75,7 +75,11 @@ public class BlockPlayoutBuilder( @@ -75,7 +75,11 @@ public class BlockPlayoutBuilder(
}
// always start at the beginning of the block
start = blocksToSchedule.Min(b => b.Start);
DateTimeOffset firstBlockStart = blocksToSchedule.Min(b => b.Start);
if (firstBlockStart < start)
{
start = firstBlockStart;
}
// get all collection items for the playout
Map<CollectionKey, List<MediaItem>> collectionMediaItems =

Loading…
Cancel
Save