Phase 7 follow-up #246 — Phase7Composer + Program.cs wire-in #193
Reference in New Issue
Block a user
Delete Branch "phase-7-fu-246-program-wireup"
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?
Activates the Phase 7 engines in production. Loads
Script+VirtualTag+ScriptedAlarmrows from the bootstrapped generation, wires the engines through thePhase7EngineComposerkernel (#243), starts theDriverSubscriptionBridgefeed (#244), and late-binds the resultingIReadablesources toOpcUaApplicationHostbefore OPC UA server start.Phase7ComposerSingleton orchestrator.
PrepareAsyncloads the three Phase 7 row sets in one DB scope, buildsCachedTagUpstreamSource, callsPhase7EngineComposer.Compose, constructsDriverSubscriptionBridgewith oneDriverFeedper registeredISubscribabledriver (path-to-fullRef map built fromEquipmentNamespaceContentviaMapPathsToFullRefs), starts the bridge.DisposeAsynctears down in the right order: bridge first (no more events fired into the cache), then engines (cascades + timers stop), then any disposable sink.MapPathsToFullRefsdeterministic path convention:/{areaName}/{lineName}/{equipmentName}/{tagName}matching exactly whatEquipmentNodeWalkeremits into the OPC UA browse tree, so script literals against the operator-visible UNS tree work without translation. Tags missingEquipmentIdor pointing at unknown Equipment are skipped silently.OpcUaApplicationHost.SetPhase7SourcesNew late-bind setter. Throws
InvalidOperationExceptionif called afterStartAsyncbecauseOtOpcUaServer+DriverNodeManagers capture the field values at construction; mutation post-start would silently fail.OpcUaServerServiceAfter bootstrap loads the current generation, calls
phase7Composer.PrepareAsync+applicationHost.SetPhase7SourcesbeforeapplicationHost.StartAsync.StopAsyncdisposesPhase7Composerfirst so the bridge stops feeding the cache before the OPC UA server tears down its node managers.Program.cs
Registers
IAlarmHistorianSinkasNullAlarmHistorianSink.Instance(task #247 swaps in the real Galaxy.Host-writer-backedSqliteStoreAndForwardSink), Serilog root logger, andPhase7Composersingleton.Tests — 5 new
Phase7ComposerMappingTests= 34 Phase 7 tests totalMaps tag → walker UNS path, skips null EquipmentId, skips unknown Equipment reference, multiple tags under same equipment map distinctly, empty content yields empty map. Pure functions; no DI/DB.
The real
PrepareAsyncDB query path can't be exercised without SQL Server in the test environment — exercised by the live E2E smoke (task #240) which unblocks once #247 lands.Phase 7 production wiring chain