fix saving yaml playout history (#2327)

* fix saving yaml playout history

* cleanup
This commit is contained in:
Jason Dove
2025-08-17 01:21:07 +00:00
committed by GitHub
parent 330195d5e3
commit 1e7f9a5709
6 changed files with 67 additions and 22 deletions
@@ -3,5 +3,30 @@ using ErsatzTV.Core.Scheduling;
namespace ErsatzTV.Application.Playouts; namespace ErsatzTV.Application.Playouts;
public record BuildPlayout(int PlayoutId, PlayoutBuildMode Mode) : IRequest<Either<BaseError, Unit>>, public record BuildPlayout : IRequest<Either<BaseError, Unit>>, IBackgroundServiceRequest
IBackgroundServiceRequest; {
public BuildPlayout(int playoutId, PlayoutBuildMode mode)
{
Start = DateTimeOffset.Now;
PlayoutId = playoutId;
Mode = mode;
}
public BuildPlayout(int playoutId, PlayoutBuildMode mode, DateTimeOffset start)
{
Start = start;
PlayoutId = playoutId;
Mode = mode;
}
public DateTimeOffset Start { get; set; }
public int PlayoutId { get; init; }
public PlayoutBuildMode Mode { get; init; }
public void Deconstruct(out int playoutId, out PlayoutBuildMode mode, out DateTimeOffset start)
{
playoutId = PlayoutId;
mode = Mode;
start = Start;
}
}
@@ -125,7 +125,12 @@ public class BuildPlayoutHandler : IRequestHandler<BuildPlayout, Either<BaseErro
cancellationToken); cancellationToken);
break; break;
case ProgramSchedulePlayoutType.Yaml: case ProgramSchedulePlayoutType.Yaml:
result = await _yamlPlayoutBuilder.Build(playout, referenceData, request.Mode, cancellationToken); result = await _yamlPlayoutBuilder.Build(
request.Start,
playout,
referenceData,
request.Mode,
cancellationToken);
break; break;
case ProgramSchedulePlayoutType.ExternalJson: case ProgramSchedulePlayoutType.ExternalJson:
await _externalJsonPlayoutBuilder.Build(playout, request.Mode, cancellationToken); await _externalJsonPlayoutBuilder.Build(playout, request.Mode, cancellationToken);
@@ -6,6 +6,7 @@ namespace ErsatzTV.Core.Interfaces.Scheduling;
public interface IYamlPlayoutBuilder public interface IYamlPlayoutBuilder
{ {
Task<PlayoutBuildResult> Build( Task<PlayoutBuildResult> Build(
DateTimeOffset start,
Playout playout, Playout playout,
PlayoutReferenceData referenceData, PlayoutReferenceData referenceData,
PlayoutBuildMode mode, PlayoutBuildMode mode,
@@ -9,7 +9,7 @@ namespace ErsatzTV.Core.Scheduling.YamlScheduling.Handlers;
public class YamlPlayoutApplyHistoryHandler(EnumeratorCache enumeratorCache) public class YamlPlayoutApplyHistoryHandler(EnumeratorCache enumeratorCache)
{ {
public async Task<bool> Handle( public async Task<bool> Handle(
PlayoutReferenceData referenceData, IReadOnlyCollection<PlayoutHistory> filteredHistory,
YamlPlayoutContext context, YamlPlayoutContext context,
YamlPlayoutContentItem contentItem, YamlPlayoutContentItem contentItem,
ILogger<YamlPlayoutBuilder> logger, ILogger<YamlPlayoutBuilder> logger,
@@ -39,7 +39,7 @@ public class YamlPlayoutApplyHistoryHandler(EnumeratorCache enumeratorCache)
string historyKey = HistoryDetails.KeyForYamlContent(contentItem); string historyKey = HistoryDetails.KeyForYamlContent(contentItem);
DateTime historyTime = context.CurrentTime.UtcDateTime; DateTime historyTime = context.CurrentTime.UtcDateTime;
Option<DateTime> maxWhen = await referenceData.PlayoutHistory Option<DateTime> maxWhen = await filteredHistory
.Filter(h => h.Key == historyKey) .Filter(h => h.Key == historyKey)
.Filter(h => h.When < historyTime) .Filter(h => h.When < historyTime)
.Map(h => h.When) .Map(h => h.When)
@@ -47,7 +47,7 @@ public class YamlPlayoutApplyHistoryHandler(EnumeratorCache enumeratorCache)
.HeadOrNone() .HeadOrNone()
.IfNoneAsync(DateTime.MinValue); .IfNoneAsync(DateTime.MinValue);
var maybeHistory = referenceData.PlayoutHistory var maybeHistory = filteredHistory
.Filter(h => h.Key == historyKey) .Filter(h => h.Key == historyKey)
.Filter(h => h.When == maxWhen) .Filter(h => h.When == maxWhen)
.ToList(); .ToList();
@@ -25,6 +25,7 @@ public class YamlPlayoutBuilder(
: IYamlPlayoutBuilder : IYamlPlayoutBuilder
{ {
public async Task<PlayoutBuildResult> Build( public async Task<PlayoutBuildResult> Build(
DateTimeOffset start,
Playout playout, Playout playout,
PlayoutReferenceData referenceData, PlayoutReferenceData referenceData,
PlayoutBuildMode mode, PlayoutBuildMode mode,
@@ -99,8 +100,6 @@ public class YamlPlayoutBuilder(
} }
} }
DateTimeOffset start = DateTimeOffset.Now;
int daysToBuild = await GetDaysToBuild(); int daysToBuild = await GetDaysToBuild();
DateTimeOffset finish = start.AddDays(daysToBuild); DateTimeOffset finish = start.AddDays(daysToBuild);
@@ -161,11 +160,18 @@ public class YamlPlayoutBuilder(
// finish, // finish,
// context.InstructionIndex); // context.InstructionIndex);
// apply all history // apply all (filtered) history
var filteredHistory = referenceData.PlayoutHistory.ToList();
filteredHistory.RemoveAll(h => result.HistoryToRemove.Contains(h.Id));
var applyHistoryHandler = new YamlPlayoutApplyHistoryHandler(enumeratorCache); var applyHistoryHandler = new YamlPlayoutApplyHistoryHandler(enumeratorCache);
foreach (YamlPlayoutContentItem contentItem in playoutDefinition.Content) foreach (YamlPlayoutContentItem contentItem in playoutDefinition.Content)
{ {
await applyHistoryHandler.Handle(referenceData, context, contentItem, logger, cancellationToken); await applyHistoryHandler.Handle(
filteredHistory.ToImmutableList(),
context,
contentItem,
logger,
cancellationToken);
} }
if (mode is PlayoutBuildMode.Reset) if (mode is PlayoutBuildMode.Reset)
@@ -286,6 +292,7 @@ public class YamlPlayoutBuilder(
playout.Anchor = anchor; playout.Anchor = anchor;
result.AddedItems.AddRange(context.AddedItems); result.AddedItems.AddRange(context.AddedItems);
result.AddedHistory.AddRange(context.AddedHistory);
return result; return result;
} }
+19 -12
View File
@@ -30,16 +30,23 @@ public class ChannelController(ChannelWriter<IBackgroundServiceRequest> workerCh
return new NotFoundResult(); return new NotFoundResult();
} }
[HttpPost("/api/channels/{channelNumber}/playout/continue")] // for debugging by fast-forwarding a YAML playout
public async Task<IActionResult> ContinuePlayout(string channelNumber) // [HttpPost("/api/channels/{channelNumber}/playout/continue")]
{ // public async Task<IActionResult> ContinuePlayout(string channelNumber)
Option<int> maybePlayoutId = await mediator.Send(new GetPlayoutIdByChannelNumber(channelNumber)); // {
foreach (int playoutId in maybePlayoutId) // Option<int> maybePlayoutId = await mediator.Send(new GetPlayoutIdByChannelNumber(channelNumber));
{ // foreach (int playoutId in maybePlayoutId)
await workerChannel.WriteAsync(new BuildPlayout(playoutId, PlayoutBuildMode.Continue)); // {
return new OkResult(); // DateTimeOffset start = DateTimeOffset.Now;
} // for (int i = 0; i < 24; i++)
// {
return new NotFoundResult(); // await workerChannel.WriteAsync(new BuildPlayout(playoutId, PlayoutBuildMode.Continue, start));
} // start += TimeSpan.FromHours(1);
// }
//
// return new OkResult();
// }
//
// return new NotFoundResult();
// }
} }