Driver-instance bootstrap pipeline (#248) — DriverInstance rows materialise as live IDriver instances #196
Reference in New Issue
Block a user
Delete Branch "phase-7-fu-248-driver-bootstrap"
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 gap surfaced by Phase 7 live smoke (#240):
DriverInstancerows in the central config DB had no path to materialise as liveIDriverinstances inDriverHost, so virtual-tag scripts readBadNodeIdUnknownfor every tag.DriverFactoryRegistry(Core.Hosting)Process-singleton type-name → factory map. Each driver project's static Register call pre-loads its factory at Program.cs startup; the bootstrapper looks up by
DriverInstance.DriverType+ invokes with(DriverInstanceId, DriverConfig JSON). Case-insensitive; duplicate-type registration throws.GalaxyProxyDriverFactoryExtensions.Register(Driver.Galaxy.Proxy)Static helper — no
Microsoft.Extensions.DependencyInjectiondep, keeps the driver project free of DI machinery. Parses DriverConfig JSON forPipeName+SharedSecret+ConnectTimeoutMs.DriverInstanceIdfrom the row wins over JSON per the schema'sUX_DriverInstance_Generation_LogicalId.DriverInstanceBootstrapper(Server)After
NodeBootstraploads the published generation: queries DriverInstance rows scoped to that generation, looks up the factory per row, constructs +DriverHost.RegisterAsync(which callsInitializeAsync). Per plan decision #12 (driver isolation), failure of one driver doesn't prevent others — logsERR+ continues + returns the count actually registered. Unknown DriverType (factory not registered) logsWRN+ skips so a missing-assembly deployment doesn't take down the whole server.Wired into
OpcUaServerService.ExecuteAsyncAfter
NodeBootstrap.LoadCurrentGenerationAsync, beforePopulateEquipmentContentAsync+Phase7Composer.PrepareAsync. The Phase 7 chain now sees a populatedDriverHostsoCachedTagUpstreamSourcehas an upstream feed.Live evidence on the dev box
Re-ran the Phase 7 smoke from #240. Pre vs post #248:
Galaxy.Host pipe ACL denied our SID (env-config issue documented in
docs/ServiceHosting.md, NOT a code issue) — the bootstrapper logged it as 'failed to initialize, driver state will reflect Faulted' and continued past the failure exactly per plan #12. The rest of the pipeline (Equipment walker + Phase 7 composer) ran to completion.Tests — 5 new
DriverFactoryRegistryTests: Register + TryGet round-trip, case-insensitive lookup, duplicate-type throws, null-arg guards, RegisteredTypes snapshot. Pure functions; no DI/DB needed. The bootstrapper's DB-query path is exercised by the live smoke (#240) which operators run before each release.