Review remediation: Lane A — Runtime driver lifecycle (fable; review fable) #731
Reference in New Issue
Block a user
Delete Branch "%!s()"
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?
From the 2026-10-21 Fable system review. Findings
R0x:IDrefer todocs/reviews/2026-10-21/0x-*.md(location, evidence, failure scenario, fix recipe). Plan:docs/superpowers/plans/2026-10-22-review-remediation.md.Lane A — Runtime driver lifecycle (fable; review fable)
Owns:
src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/**Runtime/Health/**Runtime/Telemetry/**src/Core/ZB.MOM.WW.OtOpcUa.Cluster/TelemetryOptions.cs+ the telemetry dialersrc/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriver.cssrc/Core/ZB.MOM.WW.OtOpcUa.Commons/Browsing/DiscoveryDriverBrowser.csIFleetDiagnosticsClientconsumer page (one new Razor file) +AdminUI/Clients/FleetDiagnosticsClient.csTests:
tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests,tests/Core/ZB.MOM.WW.OtOpcUa.Commons.TestsR02:L1,R02:P4,R06host context,R07:L2).DriverInstanceActor.PostStop:ShutdownAsync(cts.Token).WaitAsync(5 s), with a logged timeout. ThenDisposeAsync/Dispose, but only when the actor is stopping for good. OverridePreRestartto skip disposal, because the Props closure reuses the driver.DiscoveryDriverBrowserdisposes its throwaway driver infinally.IAsyncDisposabledriver is disposed exactly once onContext.Stop.ShutdownAsyncdoesn't pin a thread beyond 5 s.R02:H2). Add an_initInFlightgate cleared by the pipedInitializeSucceeded/Failed, and bound the teardown. Test: with a 15 s init and a 10 s cadence,ShutdownAsyncandInitializeAsyncnever overlap (record interleavings in the fake).R02:P2). RunWriteAttributeviaPipeTo, capturingSender, with a per-driver in-flight cap (default 4). Subscribe/unsubscribe stayReceiveAsync. Tests:_lastReprovisionUtc.RemoveinStopChild(R02:L2).Stale()drop-receives (R02:H5).ILoggerFactoryctor slot (R02:U5).OnAttributeValuePublishedseam to a test helper (R02:U4).DbHealthProbeActoroff-thread + 2 s command timeout (R02:P7).PollGroupEngine.Unsubscribesync callers and switch them toUnsubscribeAsync(R05:8).TelemetryLocalHub._evictedtimestamped sweep with TTL > max in-flight call (R02:L4).TelemetryDial:CallTimeoutSecondsinto the dialer'sCallOptionsdeadline (R02:U2). Test: a stalled stream is cancelled at the configured deadline.GetDiagnostics(R02:U1). Populate it from child health snapshots (real id, device counts fromGetHostStatuses, last-change time), and giveIFleetDiagnosticsClienta consumer: a per-node diagnostics panel on/fleet. That Razor file is owned here and live-verified in Wave 4.Lane gate: Runtime.Tests green. The docker-dev gate (Wave 4) shows a driver config change disposing the old instance: the
ObjectDisposed/dispose log appears, and process thread/handle counts stay flat across 20 respawns (dotnet-counters).