ServiceLevel publication before SDK binding is dropped and unchanged state can remain deduplicated #719
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?
Source-evidenced startup race
DeferredServiceLevelPublisher routes pre-binding Publish values to NullServiceLevelPublisher and SetInner only swaps the reference; it does not retain/replay the current value. OpcUaPublishActor's ServiceLevelChanged handler records publication as successful and deduplicates subsequent identical values. OtOpcUaServerHostedService binds the SDK publisher only after server startup.
Thus a ServiceLevel calculated before binding can be discarded and the same current value suppressed after binding, leaving the SDK initial level until a different state is published. This is source analysis, not a reproduced production incident. The #717 loopback spike did not exercise actor/host startup.
Sources: src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredServiceLevelPublisher.cs; src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs ServiceLevelChanged handler; src/Server/ZB.MOM.WW.OtOpcUa.Host/OpcUa/OtOpcUaServerHostedService.cs SDK publisher binding.
Acceptance
Related #717 and #615. Track separately because dropped late-bound publication also affects current deployments independent of future redundancy metadata.
Read-only design review additionally confirmed two delivery-observation gaps: SdkServiceLevelPublisher logs/swallowing missing-node or write faults makes failure look successful, and actor dedup must be invalidated after any failed publish (success A, failed B, then A must deliver A again). Moving the remembered byte alone is insufficient. Current deferred tests assert safe pre-bind calls but do not cover binding replay.
Bounded design presented for approval: serialized latest-value retention/replay including0; failed-bind candidate/latest retained with visible failure; actor remembers successful value and invalidates dedup on failure; SDK propagation; cleanup of started OPC endpoint after replay failure preserving existing admin-host startup policy. Deterministic ordering/rebind/fault tests and actual loopback Read are required, followed by review and hosted CI. No implementation has started; no change to health arithmetic, election or mutation policies. First-ever readiness/default255 remains #717, not solved by replay alone.
Reviewed fix committed and pushed as
c8e3e279b4in PR #720. Affected suite verification: 2,381 passed, 4 existing skips, zero failures. Independent root loopback rerun passed both client ServiceLevel reads (100 and 0). Fault/mutation regressions cover cache retention, binding order, SDK visibility, dedup recovery and cleanup ownership. Real Host construction-failure test proves listener closure/admin continuation; replay/stop fault injection has the composition limits documented in the PR.Hosted full CI remains required before merge and closure. No deployment or external device/historian calls. #717 Warm contract remains separate and open.
PR #714 is now merged as
4f7a07fbd3after full hosted run979 succeeded; #712/#606 are closed. PR #720 now includes that main history at head8828e999c41057ae7b9d84573228ab8caf71fe06. Its combined tree isa7ce6c7688, unchanged by the final ancestry-only main merge. All11 guard fixtures passed in the combined checkout.Required final-head run983 is queued behind the already active prior-head run980. No manual cancellation/rerun occurred. Earlier-head CI will not replace the final-head gate. #719 remains open until verified merge.
Resolved and merged in PR #720 as master
1bf8c614a9. Required final-head run #983/job3604 succeeded on8828e999c4: all steps passed, 62 TRX reports, 14,648 executed tests, 573 individual skips, zero failures, minimum 12,000, and artifact upload finalized. Full Runtime passed 829 with three existing skips. Merged treea7ce6c7688exactly equals tested tree; issue closure verified.Retained latest ServiceLevel including zero, serialized replay/binding and SDK failure visibility; actor dedup only after success and invalidates on failure. Startup binding cleanup preserves admin boot and retry ownership. Existing health arithmetic/election/mutation policies remain unchanged. Local real-client reads and ordering/failure regressions were independently reviewed. No deployment or live historian/device calls. Warm #717 remains separate and open.