docs(historian): fix-wave docs and stale comments
- Historian.md: Empty samples always Bad (writer/updater/read clamp), long-name refusal, 5 s bootstrap failure cache, AtTime after now, info-bit masking, HistoryUpdate does NOT type-check (M-1 decision), DeleteRaw needs both bounds, reverse Raw paging, the historian/historization metric prefixes, and provisioning numeric-only lines qualified as Gateway. - CLAUDE.md numeric-only lines qualified as Gateway backend. - Stale 'sole historian' lines in DriverLifecycle, ServiceHosting and the retired Wonderware stub; Client.CLI exit-code contract. - ServerHistorianOptions: Endpoint/Backend XML docs untangled, Validate() indented; Program.cs comments are backend-neutral; T10 week-test day count. Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
@@ -4,12 +4,13 @@ namespace ZB.MOM.WW.OtOpcUa.Runtime.Historian;
|
||||
|
||||
/// <summary>
|
||||
/// Binds the <c>ServerHistorian</c> configuration section that gates the server-side
|
||||
/// HistoryRead backend. When <see cref="Enabled"/> is <c>true</c>, <c>AddServerHistorian</c>
|
||||
/// registers a read-only <c>HistorianGateway</c>-backed <c>IHistorianDataSource</c> (supplied by
|
||||
/// historian. <see cref="Backend"/> selects the provider (<c>Gateway</c> by default, or <c>SqlServer</c>,
|
||||
/// whose own keys live in the <c>ServerHistorian:SqlServer</c> sub-section). When <see cref="Enabled"/> is
|
||||
/// <c>true</c>, <c>AddServerHistorian</c> registers that backend's <c>IHistorianDataSource</c> (supplied by
|
||||
/// the Host) in place of the <c>NullHistorianDataSource</c> default; otherwise the Null default
|
||||
/// survives and HistoryRead returns <c>GoodNoData</c>-empty.
|
||||
/// <para>
|
||||
/// The read client talks gRPC to the <c>ZB.MOM.WW.HistorianGateway</c> sidecar
|
||||
/// On the Gateway backend the read client talks gRPC to the <c>ZB.MOM.WW.HistorianGateway</c> sidecar
|
||||
/// (<c>historian_gateway.v1</c>) over <see cref="Endpoint"/>, authenticating with the
|
||||
/// peppered-HMAC <see cref="ApiKey"/> (<c>histgw_<id>_<secret></c>) in the
|
||||
/// <c>Authorization: Bearer</c> header. This is the READ path only — there are no
|
||||
@@ -24,17 +25,12 @@ public sealed class ServerHistorianOptions
|
||||
public const string SectionName = "ServerHistorian";
|
||||
|
||||
/// <summary>
|
||||
/// When <c>true</c>, the HistorianGateway read client is registered as the
|
||||
/// When <c>true</c>, the selected backend's data source is registered as the
|
||||
/// <c>IHistorianDataSource</c>; when <c>false</c> (the default) the no-op
|
||||
/// <c>NullHistorianDataSource</c> stays in place and HistoryRead returns empty.
|
||||
/// </summary>
|
||||
public bool Enabled { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Absolute gateway endpoint URI the read client dials (e.g. <c>https://host:5222</c>).
|
||||
/// The scheme selects the transport: <c>https://</c> = TLS, <c>http://</c> = h2c plaintext.
|
||||
/// Required when <see cref="Enabled"/> is <c>true</c>.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Selects the historian backend provider (case-insensitive). Default <c>"Gateway"</c>; the Host's
|
||||
/// <c>HistorianBackendRegistry</c> owns the set of valid names. Gateway-specific keys
|
||||
@@ -49,6 +45,12 @@ public sealed class ServerHistorianOptions
|
||||
public bool IsGatewayBackend =>
|
||||
string.Equals(Backend?.Trim(), GatewayBackendName, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Gateway backend only: absolute gateway endpoint URI the read client dials (e.g.
|
||||
/// <c>https://host:5222</c>). The scheme selects the transport: <c>https://</c> = TLS, <c>http://</c> = h2c
|
||||
/// plaintext. Required when the Gateway backend is consumed (<see cref="Enabled"/>, or an enabled
|
||||
/// <c>AlarmHistorian</c>).
|
||||
/// </summary>
|
||||
public string Endpoint { get; init; } = "";
|
||||
|
||||
/// <summary>
|
||||
@@ -129,17 +131,17 @@ public sealed class ServerHistorianOptions
|
||||
// Gateway-specific checks apply only to the Gateway backend (other backends carry their own options).
|
||||
if (IsGatewayBackend)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Endpoint))
|
||||
warnings.Add("ServerHistorian:Endpoint is empty while the historian is enabled — the read client has no gateway address to dial.");
|
||||
// archreview 06/S-11 warning parity: a non-empty but unparseable / non-absolute-http(s) Endpoint
|
||||
// is just as fatal (it throws in the gateway client factory). Warn on it here so the Runtime-side
|
||||
// registration logs describe malformed endpoints too, consistent with the Host's fail-fast
|
||||
// ServerHistorianOptionsValidator (which turns this same condition into a startup failure).
|
||||
else if (!Uri.TryCreate(Endpoint, UriKind.Absolute, out var uri)
|
||||
|| (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps))
|
||||
warnings.Add($"ServerHistorian:Endpoint ('{Endpoint}') is not an absolute http(s) URI while the historian is enabled — the read client cannot dial it (e.g. https://host:5222).");
|
||||
if (string.IsNullOrWhiteSpace(ApiKey))
|
||||
warnings.Add("ServerHistorian:ApiKey is empty while the historian is enabled — the gateway gRPC surface will reject unauthenticated calls.");
|
||||
if (string.IsNullOrWhiteSpace(Endpoint))
|
||||
warnings.Add("ServerHistorian:Endpoint is empty while the historian is enabled — the read client has no gateway address to dial.");
|
||||
// archreview 06/S-11 warning parity: a non-empty but unparseable / non-absolute-http(s) Endpoint
|
||||
// is just as fatal (it throws in the gateway client factory). Warn on it here so the Runtime-side
|
||||
// registration logs describe malformed endpoints too, consistent with the Host's fail-fast
|
||||
// ServerHistorianOptionsValidator (which turns this same condition into a startup failure).
|
||||
else if (!Uri.TryCreate(Endpoint, UriKind.Absolute, out var uri)
|
||||
|| (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps))
|
||||
warnings.Add($"ServerHistorian:Endpoint ('{Endpoint}') is not an absolute http(s) URI while the historian is enabled — the read client cannot dial it (e.g. https://host:5222).");
|
||||
if (string.IsNullOrWhiteSpace(ApiKey))
|
||||
warnings.Add("ServerHistorian:ApiKey is empty while the historian is enabled — the gateway gRPC surface will reject unauthenticated calls.");
|
||||
}
|
||||
// MaxTieClusterOverfetch is intentionally checked AFTER the Enabled early-return above:
|
||||
// the over-fetch code path only runs when a real IHistorianDataSource is wired in,
|
||||
|
||||
Reference in New Issue
Block a user