From 245db98f5e73c5f8e90f55da47c3bc38e56cdefa Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Fri, 26 Jun 2026 19:03:04 -0400 Subject: [PATCH] fix(historian-gateway): dispose recorder value-writer channel + clearer OutboxPath warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses T18 review: GatewayHistorianValueWriter is a DI singleton holding a gRPC channel — make it IAsyncDisposable so the container closes the channel gracefully at shutdown. Tighten the blank-OutboxPath warning to state startup will fail. Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii --- .../Recorder/GatewayHistorianValueWriter.cs | 8 +++++++- .../Historian/ContinuousHistorizationOptions.cs | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway/Recorder/GatewayHistorianValueWriter.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway/Recorder/GatewayHistorianValueWriter.cs index af80f717..3fa9106a 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway/Recorder/GatewayHistorianValueWriter.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway/Recorder/GatewayHistorianValueWriter.cs @@ -25,7 +25,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Recorder; /// durably queued must not be re-drained. /// /// -public sealed class GatewayHistorianValueWriter : IHistorianValueWriter +public sealed class GatewayHistorianValueWriter : IHistorianValueWriter, IAsyncDisposable { private readonly IHistorianGatewayClient _client; private readonly ILogger _logger; @@ -86,4 +86,10 @@ public sealed class GatewayHistorianValueWriter : IHistorianValueWriter return false; } } + + /// + /// Disposes the underlying gateway client (and its gRPC channel). The DI container owns this + /// writer as a singleton, so this fires once at host shutdown — closing the channel gracefully. + /// + public ValueTask DisposeAsync() => _client.DisposeAsync(); } diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Historian/ContinuousHistorizationOptions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Historian/ContinuousHistorizationOptions.cs index 1c729eef..74313a71 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Historian/ContinuousHistorizationOptions.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Historian/ContinuousHistorizationOptions.cs @@ -75,7 +75,7 @@ public sealed class ContinuousHistorizationOptions var warnings = new List(); if (!Enabled) return warnings; if (string.IsNullOrWhiteSpace(OutboxPath)) - warnings.Add("ContinuousHistorization:OutboxPath is empty while historization is enabled — the durable outbox has no directory to persist to; the recorder cannot be wired."); + warnings.Add("ContinuousHistorization:OutboxPath is empty while historization is enabled — the durable outbox has no directory to persist to; host startup will fail when the outbox is constructed. Set an absolute path on durable storage."); if (string.Equals(CommitMode, "Periodic", StringComparison.OrdinalIgnoreCase) && CommitIntervalMs <= 0) warnings.Add($"ContinuousHistorization:CommitIntervalMs is {CommitIntervalMs} — must be > 0 in Periodic commit mode; the periodic-commit loop cannot run."); return warnings;