diff --git a/CHANGELOG.md b/CHANGELOG.md
index b104e8f13..b10e43b72 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -84,6 +84,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Add disabled text color and `(D)` and `(H)` labels for disabled and hidden channels in channel list
- Graphics engine: fix subtitle path escaping and font loading
- Fix corrupt output (green artifacts) when decoding certain 10-bit content using AMD Polaris GPUs
+- Work around sequential schedule validation limit (1000/hr by Newtonsoft.Json.Schema library)
+ - Playout builds now use JsonSchema.Net library which has no validation limit
+ - Validation tool in the UI still uses Newtonsoft.Json.Schema (with 1000/hr limit) as the error output is easier to understand
### Changed
- Classic schedules: `Refresh` classic playouts from playout list; do not `Reset` them
diff --git a/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj b/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj
index a4749fe99..209bf6f44 100644
--- a/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj
+++ b/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj
@@ -16,6 +16,7 @@
+
diff --git a/ErsatzTV.Infrastructure/Scheduling/SequentialScheduleValidator.cs b/ErsatzTV.Infrastructure/Scheduling/SequentialScheduleValidator.cs
index 3062aec4e..ea994c858 100644
--- a/ErsatzTV.Infrastructure/Scheduling/SequentialScheduleValidator.cs
+++ b/ErsatzTV.Infrastructure/Scheduling/SequentialScheduleValidator.cs
@@ -1,6 +1,7 @@
using System.Globalization;
using System.IO.Abstractions;
using System.Text.Json;
+using System.Text.Json.Nodes;
using ErsatzTV.Core;
using ErsatzTV.Core.Interfaces.Scheduling;
using Microsoft.Extensions.Logging;
@@ -9,6 +10,7 @@ using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
using YamlDotNet.RepresentationModel;
using JsonSerializer = System.Text.Json.JsonSerializer;
+using JsonSchemaNet = Json.Schema;
namespace ErsatzTV.Infrastructure.Scheduling;
@@ -19,21 +21,19 @@ public class SequentialScheduleValidator(IFileSystem fileSystem, ILogger errorMessages))
+ if (!result.IsValid)
{
- logger.LogWarning("Failed to validate sequential schedule definition: {ErrorMessages}", errorMessages);
+ logger.LogWarning("Sequential schedule definition failed validation");
return false;
}
@@ -49,30 +49,27 @@ public class SequentialScheduleValidator(IFileSystem fileSystem, ILogger $"{index + 1,4}: {line}"));
}
+ // limited to 1000/hr, but only called manually from UI
public async Task> GetValidationMessages(string yaml, bool isImport)
{
try
{
- string schemaFileName = Path.Combine(
- FileSystemLayout.ResourcesCacheFolder,
- isImport ? "sequential-schedule-import.schema.json" : "sequential-schedule.schema.json");
+ string schemaFileName = GetSchemaPath(isImport);
+
using StreamReader sr = fileSystem.File.OpenText(schemaFileName);
await using var reader = new JsonTextReader(sr);
var schema = JSchema.Load(reader);
- using var textReader = new StringReader(yaml);
- var yamlStream = new YamlStream();
- yamlStream.Load(textReader);
- var schedule = JObject.Parse(Convert(yamlStream));
+ string jsonString = ConvertYamlToJsonString(yaml);
+ var schedule = JObject.Parse(jsonString);
return schedule.IsValid(schema, out IList errorMessages) ? [] : errorMessages;
}
@@ -82,13 +79,24 @@ public class SequentialScheduleValidator(IFileSystem fileSystem, ILogger