Files
lmxopcua/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ConfigSourceOptions.cs
T
Joseph Doherty 9d1e60c00c feat(mesh): ConfigSource/ConfigServe options + validator (Phase 3 dark switch)
ConfigSource:Mode = Direct (default, read central SQL) | FetchAndCache (fetch
the artifact from central over gRPC, read LocalDb). The validator fails host
start on a FetchAndCache shape that cannot fetch — no endpoints, a non-http(s)
endpoint, no shared key, or a non-positive timeout — because each otherwise
surfaces as a silent absence (a deploy that never applies). ConfigServe (the
central serve surface) takes a plain Configure: a 0 port is a valid "disabled".

Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
2026-07-22 19:03:39 -04:00

68 lines
3.0 KiB
C#

namespace ZB.MOM.WW.OtOpcUa.Cluster;
/// <summary>
/// Node-side selection of where a driver reads its deployed configuration (per-cluster mesh
/// Phase 3). The dark switch that lets a driver node stop reading <c>Deployment.ArtifactBlob</c>
/// from central SQL and instead fetch the artifact from central over gRPC and read it from the
/// pair-local LocalDb cache.
/// </summary>
public sealed class ConfigSourceOptions
{
/// <summary>Configuration section name.</summary>
public const string SectionName = "ConfigSource";
/// <summary>Read config directly from central SQL — today's behaviour, and the default.</summary>
public const string ModeDirect = "Direct";
/// <summary>Fetch the artifact from central over gRPC, cache it in LocalDb, and read from there.</summary>
public const string ModeFetchAndCache = "FetchAndCache";
/// <summary>
/// <see cref="ModeDirect"/> (default) or <see cref="ModeFetchAndCache"/>. Any other value
/// fails host start.
/// </summary>
public string Mode { get; set; } = ModeDirect;
/// <summary>
/// Central artifact-gRPC base addresses, e.g. <c>http://central-1:4055</c> (h2c ⇒ the
/// <c>http</c> scheme). Tried in order for failover. Required under
/// <see cref="ModeFetchAndCache"/>; ignored under <see cref="ModeDirect"/>.
/// </summary>
public string[] CentralFetchEndpoints { get; set; } = [];
/// <summary>
/// Shared bearer key; must equal central's <see cref="ConfigServeOptions.ApiKey"/>. Supply via
/// the environment (<c>ConfigSource__ApiKey</c>) — never commit it. Required under
/// <see cref="ModeFetchAndCache"/>.
/// </summary>
public string ApiKey { get; set; } = string.Empty;
/// <summary>Per-fetch deadline in seconds. Must be positive under <see cref="ModeFetchAndCache"/>.</summary>
public int FetchTimeoutSeconds { get; set; } = 30;
}
/// <summary>
/// Central-side artifact-serve surface (per-cluster mesh Phase 3). Configures the dedicated h2c
/// listener + shared bearer key the <c>DeploymentArtifactService</c> is exposed behind. Only
/// admin-role nodes (which hold the central SQL connection) serve.
/// </summary>
public sealed class ConfigServeOptions
{
/// <summary>Configuration section name.</summary>
public const string SectionName = "ConfigServe";
/// <summary>
/// Dedicated HTTP/2-only (h2c) listener port for the artifact gRPC service. <c>0</c> (the
/// default) disables it — nothing is bound. Must differ from the main HTTP port and from
/// <c>LocalDb:SyncListenPort</c> (h2c cannot share a cleartext HTTP/1 port).
/// </summary>
public int GrpcListenPort { get; set; }
/// <summary>
/// Shared bearer key the serve-side interceptor checks (constant-time, fail-closed: an unset
/// key rejects every call). Supply via the environment (<c>ConfigServe__ApiKey</c>) — never
/// commit it.
/// </summary>
public string ApiKey { get; set; } = string.Empty;
}