Phase 7 follow-up #247 — Galaxy.Host historian writer + SQLite sink activation #194
Reference in New Issue
Block a user
Delete Branch "phase-7-fu-247-galaxy-historian-writer"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes the historian leg of Phase 7. Scripted alarm transitions now batch-flow through the existing Galaxy.Host pipe + queue durably in a local SQLite store-and-forward when Galaxy is the registered driver, instead of being dropped into NullAlarmHistorianSink.
GalaxyHistorianWriter(Driver.Galaxy.Proxy.Ipc)IAlarmHistorianWriterimplementation. TranslatesAlarmHistorianEvent→HistorianAlarmEventDto(Stream D contract), batches via the existingGalaxyIpcClient.CallAsyncround-trip onMessageKind.HistorianAlarmEventRequest/Response, maps per-eventHistorianAlarmEventOutcomeDtobytes back toHistorianWriteOutcome(Ack/RetryPlease/PermanentFail) so the SQLite drain worker knows what to ack vs dead-letter vs retry. Empty-batch fast path. Pipe-level transport faults bubble up asGalaxyIpcExceptionwhich the SQLite sink translates to whole-batch RetryPlease per its catch contract.GalaxyProxyDriver implements IAlarmHistorianWriterMarker interface lets
Phase7Composerdiscover it via type check.WriteBatchAsyncdelegates to a thinGalaxyHistorianWriterwrapping the driver's existing_client. ThrowsInvalidOperationExceptionifInitializeAsynchasn't connected yet — the SQLite drain worker treats that as a transient batch failure and retries.Phase7Composer.ResolveHistorianSinkReplaces the injected sink dep when any registered driver implements
IAlarmHistorianWriter. ConstructsSqliteStoreAndForwardSinkat%ProgramData%/OtOpcUa/alarm-historian-queue.db(falls back to%TEMP%when ProgramData unavailable), starts the 2s drain timer, owns the sink disposable for clean teardown. When no driver provides the writer, keeps theNullAlarmHistorianSinkwired by Program.cs (#246).DisposeAsyncnow disposes in the right order: bridge → engines → owned sink → injected fallback.Tests — 7 new
GalaxyHistorianWriterMappingTests:ToDtoround-trips every field; preserves null Comment; per-byte outcome enum mapping (Ack/RetryPlease/PermanentFail) via[Theory]; unknown byte throws; ctor null-guard. The IPC round-trip itself is covered by the live Host suite (task #240) which constructs a real pipe.Server.Phase7 tests: 34/34 still pass; Galaxy.Proxy tests: 25/25 (+7 = 32 total).
Phase 7 production wiring chain — COMPLETE
What unblocks now: task #240 live OPC UA E2E smoke. With a Galaxy driver registered, scripted alarm transitions flow end-to-end through engine → SQLite queue → drain worker → Galaxy.Host IPC → Aveva Historian alarm schema. Without Galaxy, NullSink keeps the engines functional and the queue dormant.