mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-17 05:11:13 +08:00
1aed93bd03
# Description
Registration of predefined nodes could not be cancelled:
`CreateAsPredefinedNode` ran the whole create lifecycle without a token,
and a cancellation that landed inside `AddPredefinedNodeAsync` could
still leave the manager half-indexed.
**Cancellable create lifecycle.** Adds a
`NodeState.CreateAsPredefinedNode(ISystemContext, CancellationToken)`
overload. The token is threaded through the internal
`CallOnBeforeCreate` / `CreateInternal` / `CallOnAfterCreate` walk, is
checked between nodes and on each convergence pass, and is passed to
every `OnAfterCreate` override. Cancellation leaves the nodes already
completed in the created state, so a later call resumes only the
remaining ones. The existing single-argument overload is unchanged and
delegates with `default`.
**Shared registration helper.** `CustomNodeManager` and
`AsyncCustomNodeManager` each carried an identical private
`CompleteCreateLifecycleForRegistration`. Both are replaced by one
internal `NodeStateLifecycle.CompleteForRegistration`.
`AddPredefinedNodeAsync` now checks cancellation on entry, propagates it
into lifecycle completion, and checks again before
`IndexPredefinedNode`, so a cancelled registration cannot leave a node
indexed, half-created, or a behaviour replacement partially wired.
_(An earlier revision also added `RemoveExplicitlyDefinedChild`
overrides on `MethodState` and `BaseDataVariableState`. Those were
dropped in 45c6b3eb0: #4432 covers the same case inside
`CreateOrReplaceInputArguments` / `CreateOrReplaceOutputArguments` /
`CreateOrReplaceEnumStrings` by assigning the typed replacement
directly, so this PR no longer touches those files.)_
The three `<see cref="NodeState.CreateAsPredefinedNode"/>` references
(two in `src`, three occurrences in a generator template) are qualified
with the parameter list because the new overload makes the unqualified
form ambiguous (CS0419).
Public API added: one overload. No new virtual members.
## Related Issues
No tracking issue — this is a self-contained extraction from the
in-progress node-source lifecycle work, kept separate so the
cancellation semantics can be reviewed on their own.
## Testing
- `dotnet build UA.slnx -c Debug` — 0 errors, no new warnings.
- `dotnet format whitespace UA.slnx --verify-no-changes` on the changed
files — clean.
- net10.0: `Opc.Ua.Types.Tests` 9704 passed, `Opc.Ua.Server.Tests` 4965
passed, `Opc.Ua.SourceGeneration.Core.Tests` 3809 passed — 0 failures
(skips pre-existing).
New coverage: six `AsyncCustomNodeManagerTests` for the registration
cancellation seams (already-cancelled token, an already-created node not
being indexed, the helper's own check, cancellation raised from the
behaviour callback for both the replacement and same-instance paths, and
that removing a node neither deletes it nor repeats its create
lifecycle), three `NodeStateTests` for token propagation,
pre-cancellation and resumption between children.
## Checklist
- [x] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [x] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [x] I have added all necessary documentation.
- [x] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed. — ran the
three affected suites on net10.0 only; .NET Framework and the remaining
suites are left to CI.
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [ ] I have addressed **all** PR feedback received.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>