Browse Source

add scripted playout timeout setting (#2456)

* add setting for scripted playout build timeout

* update dependencies
pull/2457/head
Jason Dove 10 months ago committed by GitHub
parent
commit
18523dce64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      CHANGELOG.md
  2. 24
      ErsatzTV.Application/Configuration/Commands/UpdatePlayoutSettingsHandler.cs
  3. 1
      ErsatzTV.Application/Configuration/PlayoutSettingsViewModel.cs
  4. 8
      ErsatzTV.Application/Configuration/Queries/GetPlayoutSettingsHandler.cs
  5. 2
      ErsatzTV.Application/ErsatzTV.Application.csproj
  6. 4
      ErsatzTV.Core/Domain/ConfigElementKey.cs
  7. 8
      ErsatzTV.Core/ErsatzTV.Core.csproj
  8. 17
      ErsatzTV.Core/Scheduling/ScriptedScheduling/ScriptedPlayoutBuilder.cs
  9. 2
      ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj
  10. 4
      ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj
  11. 4
      ErsatzTV/ErsatzTV.csproj
  12. 10
      ErsatzTV/Pages/Settings/PlayoutSettings.razor

2
CHANGELOG.md

@ -52,6 +52,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -52,6 +52,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Future work will add other collection options which will pad to the full block duration
- Add page to reorder channels (edit channel numbers) using drag and drop
- New page is at **Channels** > **Edit Channel Numbers**
- Scripted schedules: add setting to configure timeout of scripted playout build
- New setting is at **Settings** > **Playout** > **Scripted Schedule Timeout**
### Fixed
- Fix green output when libplacebo tonemapping is used with NVIDIA acceleration and 10-bit output in FFmpeg Profile

24
ErsatzTV.Application/Configuration/Commands/UpdatePlayoutSettingsHandler.cs

@ -32,15 +32,31 @@ public class UpdatePlayoutSettingsHandler : IRequestHandler<UpdatePlayoutSetting @@ -32,15 +32,31 @@ public class UpdatePlayoutSettingsHandler : IRequestHandler<UpdatePlayoutSetting
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, Unit> validation = await Validate(request);
return await validation.Apply<Unit, Unit>(_ => ApplyUpdate(dbContext, request.PlayoutSettings, cancellationToken));
return await validation.Apply<Unit, Unit>(_ => ApplyUpdate(
dbContext,
request.PlayoutSettings,
cancellationToken));
}
private async Task<Unit> ApplyUpdate(TvContext dbContext, PlayoutSettingsViewModel playoutSettings, CancellationToken cancellationToken)
private async Task<Unit> ApplyUpdate(
TvContext dbContext,
PlayoutSettingsViewModel playoutSettings,
CancellationToken cancellationToken)
{
await _configElementRepository.Upsert(ConfigElementKey.PlayoutDaysToBuild, playoutSettings.DaysToBuild, cancellationToken);
await _configElementRepository.Upsert(
ConfigElementKey.PlayoutDaysToBuild,
playoutSettings.DaysToBuild,
cancellationToken);
await _configElementRepository.Upsert(
ConfigElementKey.PlayoutSkipMissingItems,
playoutSettings.SkipMissingItems, cancellationToken);
playoutSettings.SkipMissingItems,
cancellationToken);
await _configElementRepository.Upsert(
ConfigElementKey.PlayoutScriptedScheduleTimeoutSeconds,
playoutSettings.ScriptedScheduleTimeoutSeconds,
cancellationToken);
// continue all playouts to proper number of days
List<Playout> playouts = await dbContext.Playouts

1
ErsatzTV.Application/Configuration/PlayoutSettingsViewModel.cs

@ -4,4 +4,5 @@ public class PlayoutSettingsViewModel @@ -4,4 +4,5 @@ public class PlayoutSettingsViewModel
{
public int DaysToBuild { get; set; }
public bool SkipMissingItems { get; set; }
public int ScriptedScheduleTimeoutSeconds { get; set; }
}

8
ErsatzTV.Application/Configuration/Queries/GetPlayoutSettingsHandler.cs

@ -19,10 +19,16 @@ public class GetPlayoutSettingsHandler : IRequestHandler<GetPlayoutSettings, Pla @@ -19,10 +19,16 @@ public class GetPlayoutSettingsHandler : IRequestHandler<GetPlayoutSettings, Pla
Option<bool> skipMissingItems =
await _configElementRepository.GetValue<bool>(ConfigElementKey.PlayoutSkipMissingItems, cancellationToken);
Option<int> scriptedScheduleTimeoutSeconds =
await _configElementRepository.GetValue<int>(
ConfigElementKey.PlayoutScriptedScheduleTimeoutSeconds,
cancellationToken);
return new PlayoutSettingsViewModel
{
DaysToBuild = await daysToBuild.IfNoneAsync(2),
SkipMissingItems = await skipMissingItems.IfNoneAsync(false)
SkipMissingItems = await skipMissingItems.IfNoneAsync(false),
ScriptedScheduleTimeoutSeconds = await scriptedScheduleTimeoutSeconds.IfNoneAsync(30)
};
}
}

2
ErsatzTV.Application/ErsatzTV.Application.csproj

@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="Serilog.Formatting.Compact.Reader" Version="4.0.0" />
<PackageReference Include="WebMarkupMin.Core" Version="2.19.0" />
<PackageReference Include="Winista.MimeDetect" Version="1.1.0" />

4
ErsatzTV.Core/Domain/ConfigElementKey.cs

@ -46,6 +46,10 @@ public class ConfigElementKey @@ -46,6 +46,10 @@ public class ConfigElementKey
public static ConfigElementKey LibraryRefreshInterval => new("scanner.library_refresh_interval");
public static ConfigElementKey PlayoutDaysToBuild => new("playout.days_to_build");
public static ConfigElementKey PlayoutSkipMissingItems => new("playout.skip_missing_items");
public static ConfigElementKey PlayoutScriptedScheduleTimeoutSeconds =>
new("playout.scripted_schedule_timeout_seconds");
public static ConfigElementKey XmltvTimeZone => new("xmltv.time_zone");
public static ConfigElementKey XmltvDaysToBuild => new("xmltv.days_to_build");
public static ConfigElementKey XmltvBlockBehavior => new("xmltv.block_behavior");

8
ErsatzTV.Core/ErsatzTV.Core.csproj

@ -25,12 +25,12 @@ @@ -25,12 +25,12 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NCalcSync" Version="5.6.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NCalcSync" Version="5.7.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="Serilog" Version="4.3.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="SkiaSharp" Version="3.119.0" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="3.119.0" />
<PackageReference Include="SkiaSharp" Version="3.119.1" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="3.119.1" />
<PackageReference Include="System.CommandLine" Version="2.0.0-rc.1.25451.107" />
<PackageReference Include="TimeSpanParserUtil" Version="1.2.0" />
<PackageReference Include="YamlDotNet" Version="16.3.0" />

17
ErsatzTV.Core/Scheduling/ScriptedScheduling/ScriptedPlayoutBuilder.cs

@ -29,6 +29,8 @@ public class ScriptedPlayoutBuilder( @@ -29,6 +29,8 @@ public class ScriptedPlayoutBuilder(
Guid buildId = scriptedPlayoutBuilderService.StartSession(schedulingEngine);
var timeoutSeconds = 30;
try
{
var args = CommandLineParser.SplitCommandLine(playout.ScheduleFile).ToList();
@ -72,7 +74,16 @@ public class ScriptedPlayoutBuilder( @@ -72,7 +74,16 @@ public class ScriptedPlayoutBuilder(
schedulingEngine.RestoreOrReset(Optional(playout.Anchor));
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
Option<int> maybeTimeoutSeconds = await configElementRepository.GetValue<int>(
ConfigElementKey.PlayoutScriptedScheduleTimeoutSeconds,
cancellationToken);
foreach (int seconds in maybeTimeoutSeconds)
{
timeoutSeconds = seconds;
}
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds));
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cts.Token);
Command command = Cli.Wrap(scriptFile)
@ -99,8 +110,8 @@ public class ScriptedPlayoutBuilder( @@ -99,8 +110,8 @@ public class ScriptedPlayoutBuilder(
}
catch (OperationCanceledException)
{
logger.LogWarning("Scripted playout build timed out after 30 seconds");
throw new TimeoutException("Scripted playout build timed out after 30 seconds");
logger.LogWarning("Scripted playout build timed out after {TimeoutSeconds} seconds", timeoutSeconds);
throw new TimeoutException($"Scripted playout build timed out after {timeoutSeconds} seconds");
}
catch (Exception ex)
{

2
ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj

@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
<ItemGroup>
<PackageReference Include="CliWrap" Version="3.9.0" />
<PackageReference Include="Hardware.Info" Version="101.0.1.1" />
<PackageReference Include="Hardware.Info" Version="101.1.0" />
<PackageReference Include="LanguageExt.Core" Version="4.4.9" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.9" />

4
ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj

@ -34,9 +34,9 @@ @@ -34,9 +34,9 @@
<PackageReference Include="Refit.Newtonsoft.Json" Version="8.0.0" />
<PackageReference Include="Refit.Xml" Version="8.0.0" />
<PackageReference Include="RichTextKit.Stbear" Version="0.4.167.3" />
<PackageReference Include="Scriban.Signed" Version="6.3.0" />
<PackageReference Include="Scriban.Signed" Version="6.4.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
<PackageReference Include="SkiaSharp" Version="3.119.0" />
<PackageReference Include="SkiaSharp" Version="3.119.1" />
<PackageReference Include="TagLibSharp" Version="2.3.0" />
<PackageReference Include="TimeZoneConverter" Version="7.0.0" />
</ItemGroup>

4
ErsatzTV/ErsatzTV.csproj

@ -55,9 +55,9 @@ @@ -55,9 +55,9 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="MudBlazor" Version="8.12.0" />
<PackageReference Include="NaturalSort.Extension" Version="4.3.0" />
<PackageReference Include="NaturalSort.Extension" Version="4.4.0" />
<PackageReference Include="Refit.HttpClientFactory" Version="8.0.0" />
<PackageReference Include="Scalar.AspNetCore" Version="2.8.1" />
<PackageReference Include="Scalar.AspNetCore" Version="2.8.6" />
<PackageReference Include="Serilog" Version="4.3.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />

10
ErsatzTV/Pages/Settings/PlayoutSettings.razor

@ -27,6 +27,12 @@ @@ -27,6 +27,12 @@
<MudText Typo="Typo.caption" Style="font-weight: normal">Controls whether file-not-found or unavailable items should be included in playouts</MudText>
</MudCheckBox>
</MudStack>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Scripted Schedule Timeout</MudText>
</div>
<MudTextField @bind-Value="_playoutSettings.ScriptedScheduleTimeoutSeconds" Validation="@(new Func<int, string>(ValidateScriptedScheduleTimeoutSeconds))" Required="true" RequiredError="Scripted schedule timeout is required!" Adornment="Adornment.End" AdornmentText="seconds"/>
</MudStack>
</MudContainer>
</div>
</MudForm>
@ -54,7 +60,7 @@ @@ -54,7 +60,7 @@
try
{
_playoutSettings = await Mediator.Send(new GetPlayoutSettings(), token);
_playoutSuccess = _playoutSettings.DaysToBuild > 0;
_playoutSuccess = _playoutSettings.DaysToBuild > 0 && _playoutSettings.ScriptedScheduleTimeoutSeconds >= 10;
}
catch (OperationCanceledException)
{
@ -64,6 +70,8 @@ @@ -64,6 +70,8 @@
private static string ValidatePlayoutDaysToBuild(int daysToBuild) => daysToBuild <= 0 ? "Playout days to build must be greater than zero" : null;
private static string ValidateScriptedScheduleTimeoutSeconds(int seconds) => seconds < 10 ? "Scripted schedule timeout seconds must be at least 10" : null;
private async Task SavePlayoutSettings()
{
await _form.Validate();

Loading…
Cancel
Save