feat(historian-gateway): alarm-write cutover — AddAlarmHistorian drains to GatewayAlarmHistorianWriter
Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
This commit is contained in:
@@ -23,7 +23,6 @@ using ZB.MOM.WW.OtOpcUa.Host.Logging;
|
||||
using ZB.MOM.WW.OtOpcUa.Host.Observability;
|
||||
using ZB.MOM.WW.OtOpcUa.Host.OpcUa;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client;
|
||||
using ZB.MOM.WW.OtOpcUa.OpcUaServer;
|
||||
using ZB.MOM.WW.OtOpcUa.Runtime.Historian;
|
||||
using ZB.MOM.WW.OtOpcUa.Runtime.Scripting;
|
||||
@@ -96,17 +95,23 @@ if (hasDriver)
|
||||
|
||||
// Config-gated durable alarm-historian sink. When the AlarmHistorian section is enabled this
|
||||
// overrides the NullAlarmHistorianSink default from AddOtOpcUaRuntime (last registration wins)
|
||||
// with a SqliteStoreAndForwardSink draining to the Wonderware TCP writer. The writer is
|
||||
// injected here because the Host is the only project that references the Wonderware client —
|
||||
// Runtime owns the gating + Sqlite construction, the Host supplies the concrete downstream.
|
||||
// with a SqliteStoreAndForwardSink draining to the gateway SendEvent writer. The alarm-write path
|
||||
// targets the SAME single gateway as the read path, so its connection (endpoint/key/TLS) is sourced
|
||||
// from the ServerHistorian section — NOT the legacy Wonderware-shaped AlarmHistorian host/port.
|
||||
// AlarmHistorianOptions still supplies the Enabled gate + the SQLite store-and-forward knobs
|
||||
// (consumed inside AddAlarmHistorian), so its Wonderware connection fields are intentionally unused.
|
||||
// Runtime owns the gating + Sqlite construction; the Host supplies the concrete gateway downstream
|
||||
// via the driver factory (which owns the package-client adapter). The writer builds its OWN gateway
|
||||
// channel — a second channel to the same sidecar: sharing one channel with the read path would force
|
||||
// the read-side GatewayHistorianDataSource to stop owning + disposing its client (regressing the read
|
||||
// cutover), and a second channel to a co-located sidecar is cheap (the gateway pools the historian
|
||||
// sessions server-side).
|
||||
var serverHistorianOptions = builder.Configuration
|
||||
.GetSection(ServerHistorianOptions.SectionName).Get<ServerHistorianOptions>()
|
||||
?? new ServerHistorianOptions();
|
||||
builder.Services.AddAlarmHistorian(
|
||||
builder.Configuration,
|
||||
(opts, sp) => new WonderwareHistorianClient(
|
||||
new WonderwareHistorianClientOptions(opts.Host, opts.Port, opts.SharedSecret)
|
||||
{
|
||||
UseTls = opts.UseTls, ServerCertThumbprint = opts.ServerCertThumbprint,
|
||||
},
|
||||
sp.GetService<ILogger<WonderwareHistorianClient>>()));
|
||||
(_, sp) => GatewayHistorian.CreateAlarmWriter(serverHistorianOptions, sp));
|
||||
|
||||
// Config-gated server-side HistoryRead backend. When the ServerHistorian section is enabled this
|
||||
// overrides the NullHistorianDataSource default from AddOtOpcUaRuntime (last registration wins) with
|
||||
|
||||
Reference in New Issue
Block a user