feat(options): eager startup validation for site-pipeline options (SiteRuntime, S&F, SiteEventLog) (arch-review 08 §1.5)

Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
This commit is contained in:
Joseph Doherty
2026-07-10 06:51:05 -04:00
parent af2cfde484
commit 8b775f4ae1
10 changed files with 342 additions and 3 deletions
@@ -1,3 +1,5 @@
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using ZB.MOM.WW.ScadaBridge.AuditLog;
using ZB.MOM.WW.ScadaBridge.ClusterInfrastructure;
using ZB.MOM.WW.ScadaBridge.Communication;
@@ -121,10 +123,33 @@ public static class SiteServiceRegistration
// Options binding
BindSharedOptions(services, config);
services.Configure<SiteRuntimeOptions>(config.GetSection("ScadaBridge:SiteRuntime"));
// Bind + eagerly validate the site-pipeline options. The validators live with their
// owner component projects (SiteRuntime / StoreAndForward / SiteEventLogging) per the
// "options classes owned by component projects" convention, but these three sections
// are bound HERE in the Host (not in a component SCE), so both the ValidateOnStart()
// chain and the TryAddEnumerable validator registration happen here. A bad section
// fails fast at host build with a clear, key-naming message instead of crashing an
// actor / hosted service later with an opaque ArgumentOutOfRangeException.
services.AddOptions<SiteRuntimeOptions>()
.Bind(config.GetSection("ScadaBridge:SiteRuntime"))
.ValidateOnStart();
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IValidateOptions<SiteRuntimeOptions>, SiteRuntimeOptionsValidator>());
services.Configure<DataConnectionOptions>(config.GetSection("ScadaBridge:DataConnection"));
services.Configure<StoreAndForwardOptions>(config.GetSection("ScadaBridge:StoreAndForward"));
services.Configure<SiteEventLogOptions>(config.GetSection("ScadaBridge:SiteEventLog"));
services.AddOptions<StoreAndForwardOptions>()
.Bind(config.GetSection("ScadaBridge:StoreAndForward"))
.ValidateOnStart();
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IValidateOptions<StoreAndForwardOptions>, StoreAndForwardOptionsValidator>());
services.AddOptions<SiteEventLogOptions>()
.Bind(config.GetSection("ScadaBridge:SiteEventLog"))
.ValidateOnStart();
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IValidateOptions<SiteEventLogOptions>, SiteEventLogOptionsValidator>());
}
/// <summary>Binds shared options sections (Node, Cluster, Database, Communication, etc.) used by both site and central roles.</summary>