refactor: ScadaBridge validators onto OptionsValidatorBase (messages unchanged)

This commit is contained in:
Joseph Doherty
2026-06-01 18:56:04 -04:00
parent 9bca6aae61
commit aac59c9fae
8 changed files with 93 additions and 164 deletions
@@ -1,4 +1,4 @@
using Microsoft.Extensions.Options;
using ZB.MOM.WW.Configuration;
namespace ZB.MOM.WW.ScadaBridge.HealthMonitoring;
@@ -14,51 +14,34 @@ namespace ZB.MOM.WW.ScadaBridge.HealthMonitoring;
/// <c>ValidateOnStart()</c> so a bad <c>ScadaBridge:HealthMonitoring</c> section
/// fails fast at boot with a clear, key-naming message.
/// </summary>
public sealed class HealthMonitoringOptionsValidator : IValidateOptions<HealthMonitoringOptions>
public sealed class HealthMonitoringOptionsValidator : OptionsValidatorBase<HealthMonitoringOptions>
{
/// <summary>
/// Validates the health monitoring options, returning a failure result if any interval values are non-positive.
/// Validates the health monitoring options, recording a failure if any interval values are non-positive.
/// </summary>
/// <param name="name">Named options instance name (unused).</param>
/// <param name="builder">The accumulator to record failures on.</param>
/// <param name="options">The health monitoring options to validate.</param>
public ValidateOptionsResult Validate(string? name, HealthMonitoringOptions options)
protected override void Validate(ValidationBuilder builder, HealthMonitoringOptions options)
{
var failures = new List<string>();
builder.RequireThat(options.ReportInterval > TimeSpan.Zero,
$"ScadaBridge:HealthMonitoring:ReportInterval must be a positive duration " +
$"(was {options.ReportInterval}); it is used directly as a PeriodicTimer period.");
if (options.ReportInterval <= TimeSpan.Zero)
{
failures.Add(
$"ScadaBridge:HealthMonitoring:ReportInterval must be a positive duration " +
$"(was {options.ReportInterval}); it is used directly as a PeriodicTimer period.");
}
builder.RequireThat(options.OfflineTimeout > TimeSpan.Zero,
$"ScadaBridge:HealthMonitoring:OfflineTimeout must be a positive duration " +
$"(was {options.OfflineTimeout}); it drives the offline-check PeriodicTimer cadence.");
if (options.OfflineTimeout <= TimeSpan.Zero)
{
failures.Add(
$"ScadaBridge:HealthMonitoring:OfflineTimeout must be a positive duration " +
$"(was {options.OfflineTimeout}); it drives the offline-check PeriodicTimer cadence.");
}
builder.RequireThat(options.CentralOfflineTimeout > TimeSpan.Zero,
$"ScadaBridge:HealthMonitoring:CentralOfflineTimeout must be a positive duration " +
$"(was {options.CentralOfflineTimeout}).");
if (options.CentralOfflineTimeout <= TimeSpan.Zero)
{
failures.Add(
$"ScadaBridge:HealthMonitoring:CentralOfflineTimeout must be a positive duration " +
$"(was {options.CentralOfflineTimeout}).");
}
if (options.OfflineTimeout > TimeSpan.Zero
&& options.CentralOfflineTimeout > TimeSpan.Zero
&& options.CentralOfflineTimeout < options.OfflineTimeout)
{
failures.Add(
$"ScadaBridge:HealthMonitoring:CentralOfflineTimeout ({options.CentralOfflineTimeout}) " +
$"must be >= OfflineTimeout ({options.OfflineTimeout}): the synthetic 'central' site has " +
"no heartbeat source and is fed only by the slower self-report loop, so it needs at " +
"least as much offline grace as a real site.");
}
return failures.Count > 0
? ValidateOptionsResult.Fail(failures)
: ValidateOptionsResult.Success;
builder.RequireThat(
!(options.OfflineTimeout > TimeSpan.Zero
&& options.CentralOfflineTimeout > TimeSpan.Zero
&& options.CentralOfflineTimeout < options.OfflineTimeout),
$"ScadaBridge:HealthMonitoring:CentralOfflineTimeout ({options.CentralOfflineTimeout}) " +
$"must be >= OfflineTimeout ({options.OfflineTimeout}): the synthetic 'central' site has " +
"no heartbeat source and is fed only by the slower self-report loop, so it needs at " +
"least as much offline grace as a real site.");
}
}
@@ -12,6 +12,7 @@
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Options" />
<PackageReference Include="ZB.MOM.WW.Configuration" />
</ItemGroup>
<ItemGroup>