Repository navigation
Client: admission controls for automatic communication recovery of managed sessions - #4902
cristipogacean wants to merge 1 commit into
Conversation
Preserve default recovery while supporting consecutive keep-alive failure thresholds, disabled automatic communication recovery and explicit session-owned transports. Wire options, fluent APIs and DI; reject independent channel-manager recovery when it would bypass policy. Initial retries and manual reconnect remain available. Validation: 501 related net10 tests and 182 policy/builder/state-machine net48 tests passed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code coverage✅ Coverage gate passed.
Coverage is above the recorded baseline - consider ratcheting Thresholds live in |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #4902 +/- ##
=======================================
Coverage 83.36% 83.36%
=======================================
Files 3504 3504
Lines 509312 509367 +55
Branches 86474 86487 +13
=======================================
+ Hits 424587 424637 +50
+ Misses 55938 55934 -4
- Partials 28787 28796 +9
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
🟡 Changes recommended
Custom factories can return managed transports without populating Session.ChannelManager, bypassing admission validation and allowing independent recovery.
1 open issue
What changed in this PR
Adds optional communication-recovery admission controls to ManagedSession, addressing #4895 while preserving default behavior and compatibility with reverse-connection recovery.
Changes:
- Adds a consecutive keep-alive failure threshold, automatic recovery toggle, and session-owned transport selection.
- Exposes the controls through options, fluent configuration, and dependency injection, with validation for incompatible channel-manager configurations.
- Documents recovery semantics and adds admission, retry, builder, and validation tests.
| File | Description |
|---|---|
tests/Opc.Ua.Client.Tests/Session/ManagedSessionRecoveryAdmissionTests.cs |
Tests admission thresholds, manual recovery, and transport restrictions. |
tests/Opc.Ua.Client.Tests/Session/ConnectionStateMachineTests.cs |
Tests recovery-cycle rearming with automatic recovery enabled or disabled. |
tests/Opc.Ua.Client.Tests/ClientBuilder/OpcUaClientBuilderTests.cs |
Tests option propagation and validation through dependency injection. |
tests/Opc.Ua.Client.Tests/ClientBuilder/ManagedSessionBuilderTests.cs |
Tests fluent defaults, transport selection, and invalid combinations. |
src/Opc.Ua.Client/Session/Reconnect/ConnectionStateMachine.cs |
Makes recovery-cycle rearming configurable. |
src/Opc.Ua.Client/Session/ManagedSessionOptions.cs |
Defines the three admission and transport options. |
src/Opc.Ua.Client/Session/ManagedSession.cs |
Applies admission controls and validates transport compatibility. |
src/Opc.Ua.Client/Fluent/OpcUaClientBuilderExtensions.cs |
Wires options and validation into dependency injection. |
src/Opc.Ua.Client/Fluent/ManagedSessionBuilder.cs |
Adds fluent recovery and transport configuration. |
docs/Sessions.md |
Documents admission behavior, restrictions, and usage. |
Review effort: Balanced
| await managed.StateMachine | ||
| .WaitForConnectedAsync(ct) | ||
| .ConfigureAwait(false); | ||
| if (customAdmission && managed.InnerSession.ChannelManager != null) |
|
Closing per the review discussion with @marcschier (2026-10-26): not needed in the stack. The consuming application will use the existing managed-session reconnect configuration (ReconnectPolicyOptions / IReconnectPolicy) instead of adding recovery-admission options. |

Description
Adds optional, additive admission controls for the automatic communication recovery of
ManagedSession. They are available throughManagedSessionOptions, the fluentManagedSessionBuilderand DI. The defaults keep today's behavior.KeepAliveFailureThreshold(default1)ReconnectOnCommunicationFailure(defaulttrue)false, communication failures do not start automatic recovery, and an exhausted recovery cycle is not re-armed. Initial connection retries and explicitReconnectAsynckeep working.UseSharedChannelManager(defaulttrue)false, the session uses its own transport even if the host registers a shared channel manager.A shared channel manager recovers channels on its own, so it cannot honor per-session admission. Combining custom admission with a shared manager is rejected, not silently ignored:
ReconnectAsync.Fluent API:
WithCommunicationRecovery(...)andWithoutChannelManager().Integration with recent master changes
IReverseConnectionSourcegoes through the session's own factory. The admission controls apply to when recovery starts, not to how the connection is obtained.ReconnectOnCommunicationFailure = falsedoes not disable redundancy failover, which is a separate, opt-in feature. Reviewers: should it? If so, I'll add that here.Documentation:
docs/Sessions.md.Related Issues
Checklist
Validation
Branch based on
masteratf3980f9e7.Release.dotnet build tests/Opc.Ua.Client.Tests/Opc.Ua.Client.Tests.csproj -c Release(CustomTestTarget=net10.0)dotnet format whitespace <project> --verify-no-changes --include <changed files>dotnet test tests/Opc.Ua.Client.Tests/bin/Release/net10.0/Opc.Ua.Client.Tests.dll --filter "<recovery admission, builders, state machine, managed session, session, recovery, reconnect, channel manager, reverse connect fixtures>"(CustomTestTarget=net10.0)dotnet test tests/Opc.Ua.Client.Tests/Opc.Ua.Client.Tests.csproj -c Release -f net10.0 --filter "TestCategory!=LongRunning&TestCategory!=Stress"(CustomTestTarget=net10.0)dotnet test tests/Opc.Ua.Sessions.Tests/Opc.Ua.Sessions.Tests.csproj -c Release -f net10.0 --filter "TestCategory!=LongRunning&TestCategory!=Stress"(CustomTestTarget=net10.0)dotnet test tests/Opc.Ua.Client.Tests/Opc.Ua.Client.Tests.csproj -c Release -f net48 --filter "TestCategory!=LongRunning&TestCategory!=Stress"(CustomTestTarget=net48)Draft: the full
UA.slnxmatrix runs in CI.