Model Server.ServerRedundancy via generated subtype instances (#3981) - #9
Merged
marcschier merged 3 commits intoJul 10, 2026
Merged
Conversation
…ndation#3981) Expose Server.ServerRedundancy as the correct generated subtype (TransparentRedundancyState / NonTransparentRedundancyState / ServerRedundancyState) for the configured RedundancySupport mode, with mode-specific children (CurrentServerId / ServerUriArray) coming from the generated model instead of hand-written PropertyState construction. No hardcoded numeric redundancy type NodeIds remain. - Add generic core primitive AsyncCustomNodeManager.ReplacePredefinedInstanceSubtypeAsync (+ IDiagnosticsNodeManager) that swaps a predefined instance node for a differently-typed instance, preserving identity, well-known child NodeIds and values, and emitting a ModelChange. - Add ServerRedundancyController (IServerRedundancyController) with runtime ChangeModeAsync + RedundancySupport->ObjectTypeIds mapping; ServerRedundancyStartupTask now delegates to it. - Simplify DiagnosticsNodeManager: drop hand-written CurrentServerId/ServerUriArray helpers and dynamic TypeDefinitionId mutation. - Tests: subtype/browse-model assertions incl. runtime mode change; core primitive unit tests.
marcschier
commented
Jul 10, 2026
…PubSub samples to ghcr (OPCFoundation#3984) - Add Dockerfiles for ConsoleLdsServer, MinimalBoilerServer, MinimalCalcServer, PumpDeviceIntegrationServer, McpServer (aspnet base for HTTP/SSE), and ConsoleReferencePubSubClient (root-context build, net10.0, PublishAot=false). - Rewrite .github/workflows/docker-image.yml into a matrix that builds and pushes all 10 sample images (refserver, ldsserver, boilerserver, calcserver, pumpserver, mcpserver, redundantserver, redundantclient, redundantpubsub, pubsubclient) to ghcr on the existing ubuntu-latest runner, with per-image gha build cache scopes and fail-fast disabled. - Document the additional images in Docs/ContainerReferenceServer.md.
…ment (OPCFoundation#3981) - Move ReplacePredefinedInstanceSubtypeAsync into its own capability interface IPredefinedNodeSubtypeReplacer implemented by AsyncCustomNodeManager; remove it from IDiagnosticsNodeManager. ServerRedundancyController now resolves the capability via 'server.DiagnosticsNodeManager as IPredefinedNodeSubtypeReplacer'. - Document the capability (usage example, when/when-not to use, reuse candidates, and the fluent-API rationale) in Docs/CoreNodeManagerVsCustomNodeManager2.md. - Trim the user-facing ServerRedundancy subtype paragraph and reword the runtime paragraph to focus on IServerRedundancyController.ChangeModeAsync in Docs/HighAvailability.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Refactors the
Server.ServerRedundancyaddress-space modeling to materialize the correct generated subtype instance for the configuredRedundancySupportmode instead of keeping a single baseServerRedundancyState, mutating itsTypeDefinitionId, and adding the mode-specific children (CurrentServerId/ServerUriArray) via hand-writtenPropertyStateconstruction.Server.ServerRedundancyis now exposed as:TransparentRedundancyType(TransparentRedundancyState) forTransparent— with the generatedCurrentServerId,NonTransparentRedundancyType(NonTransparentRedundancyState) forCold/Warm/Hot/HotAndMirrored— with the generatedServerUriArray,ServerRedundancyTypeforNone.The mode-specific members come from the generated information model rather than hand-built
PropertyStatenodes, and no hardcoded numeric redundancy-type NodeIds remain (ObjectTypeIds.*are used throughout). The well-known instance NodeIds (Server_ServerRedundancy_RedundancySupport,_RedundantServerArray,_CurrentServerId,_ServerUriArray) and values are preserved when the node is promoted to the subtype.What changed
Generic core primitive (
Opc.Ua.Server)AsyncCustomNodeManager.ReplacePredefinedInstanceSubtypeAsync(...), exposed via its ownIPredefinedNodeSubtypeReplacercapability interface (documented inDocs/CoreNodeManagerVsCustomNodeManager2.md). It replaces a registered predefined instance node with a differently-typed instance (e.g. a generated subtype), preserving the node's identity (NodeId,BrowseName, parent), copying overlapping children's NodeIds and values by BrowseName, assigning caller-supplied well-known NodeIds to subtype-only children, swapping the address-space index, and emitting aModelChange. It is generic and reusable beyond redundancy, and builds on the source-generator-provided typedCreateInstanceOf<Type>factories.Server redundancy (
Opc.Ua.Redundancy.Server)ServerRedundancyController/IServerRedundancyControllerwith:RedundancySupport → ObjectTypeIds.*mapping (GetTypeDefinitionId),ChangeModeAsync(mode)that re-materializesServer.ServerRedundancyas the new subtype in place and raises aModelChangeso connected clients observe the new type definition/members.ServerRedundancyStartupTaskis now a thin delegate to the controller; the DI registration wires the controller andIServerRedundancyController.Core
DiagnosticsNodeManagerAddServerRedundancyStringProperty/AddServerRedundancyStringArrayPropertyand the dynamicApplyServerRedundancyTypeDefinitionmutation; keeps only the generatedAddRedundantServerArrayoptional-child helper on the base node.Design notes
CreateInstanceOf<Subtype>factories, generated subtype state classes, generatedAddRedundantServerArray,ObjectTypeIds/VariableIds, and the generic activator-basedNodeStateFactorydispatch). It is OK to break back-compat here as the redundancy area is new in 2.0.CurrentServerId/ServerUriArrayas orphaned loose predefined nodes (no parent); the promotion adopts the mode's member as a typed subtype child at its well-known NodeId and drops the other mode's member.Related Issues
nodestatestorage).Testing
Opc.Ua.Redundancy.Server.Tests: full suite green (492/492 on net10.0), including new subtype/browse-model assertions and a runtime mode-change test.Opc.Ua.Server.Tests: newReplacePredefinedInstanceSubtypeAsyncunit tests (identity/child-NodeId preservation, argument validation).Opc.Ua.InformationModel.TestsRedundancyModelTestsconformance: green.Checklist