Skip to content

[master378] Send the filtered retain trailing event with a client specific Retain = false - #4454

Merged
marcschier merged 1 commit into
master378from
romanett/opc-ua-dotnet-4449-master378
Sep 8, 2026
Merged

[master378] Send the filtered retain trailing event with a client specific Retain = false#4454
marcschier merged 1 commit into
master378from
romanett/opc-ua-dotnet-4449-master378

Conversation

@romanett

@romanett romanett commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Description

Backport of #4453 to the 1.5.378 line.

When SupportsFilteredRetain is true and a condition drops out of a client's where clause, the server sends one trailing event to that client. Before this change the trailing event carried the condition's real Retain value, typically true, so a spec-following client kept an alarm on its display that it should have dropped. OPC 10000-9, 5.5.2 (Figure 11) and the "Retain sent" column of Table B.3 require that event to be sent with a client specific Retain = false.

The value is per client and per filter, so it is applied inside the monitored item:

  • CanSendFilteredAlarm gains an out bool overrideRetain parameter that is true only for the trailing out-of-scope event. The protected signature is changed in place rather than overloaded.
  • For that event the event fields are read through a new internal FilteredRetainTarget decorator. It delegates everything to the original IFilterTarget and returns false for a Retain value clause the target actually resolves. A clause the type check rejects stays null so the field list keeps its shape.
  • The shared InstanceStateSnapshot that ReportEvent fans out to every monitored item is never touched, so other subscriptions whose filter the condition still passes keep receiving the server's real value. The queued EventFieldList keeps the original instance as its Handle, so reference-based duplicate detection and node manager handle lookups are unaffected.

Differences from the master change: this branch has neither the #4377 filtered-retain rework nor docs/AlarmsAndConditions.md, so the decorator is written against the object-based IFilterTarget of this line, the existing tracking logic is left as it is, and there is no documentation change. The reflection-based test helper reads the new out parameter back from the argument array.

Tests added in FilterRetainTests:

  • the step-5 event from the issue queued through two monitored items sharing one snapshot: the out-of-scope client receives Retain = false, the still-passing client receives true, and the snapshot itself still reports true;
  • the override applies to the single trailing event only and the server value returns once the condition re-enters scope;
  • an unresolvable Retain clause stays null;
  • the existing 16-step Table B.3 test now also asserts the "Retain sent" column for the trailing rows.

Related Issues

Checklist

  • I have signed the CLA and read the CONTRIBUTING doc.
  • I have added tests that prove my fix is effective or that my feature works and increased code coverage.
  • I have added all necessary documentation.
  • 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.
  • 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

@romanett romanett added the 1.5.378 Only affects 1.5.378 (pre 2.0) label Sep 8, 2026
@codecov

codecov Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.85714% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.35%. Comparing base (0744066) to head (786ac39).

Files with missing lines Patch % Lines
...Subscription/MonitoredItem/FilteredRetainTarget.cs 88.88% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##           master378    #4454      +/-   ##
=============================================
- Coverage      60.35%   60.35%   -0.01%     
=============================================
  Files            378      379       +1     
  Lines          79155    79181      +26     
  Branches       13850    13853       +3     
=============================================
+ Hits           47777    47788      +11     
- Misses         26961    26976      +15     
  Partials        4417     4417              
Files with missing lines Coverage Δ
...Server/Subscription/MonitoredItem/MonitoredItem.cs 64.42% <100.00%> (+1.36%) ⬆️
...Subscription/MonitoredItem/FilteredRetainTarget.cs 88.88% <88.88%> (ø)

... and 8 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…cific Retain = false

Backport of #4453. With SupportsFilteredRetain the trailing event a
condition produces on its way out of a client's where clause was
delivered with the server's Retain value, usually true, so a client
following Part 9 kept an alarm it should have dropped. Part 9, 5.5.2
(Figure 11) and the "Retain sent" column of Table B.3 require that
event to carry Retain = false.

CanSendFilteredAlarm now reports the trailing event through an out
parameter, and for that event the fields are read through a decorator
that returns false for the Retain clause. The shared snapshot is left
untouched so other subscriptions still see the server's value, and the
queued event keeps the original handle for duplicate detection.

Fixes #4449 for 1.5.378

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@romanett
romanett requested a review from marcschier September 8, 2026 17:52
@marcschier marcschier added the ready Ready to merge once CI Passes label Sep 8, 2026
@marcschier
marcschier enabled auto-merge (squash) September 8, 2026 17:58
@marcschier
marcschier merged commit 5c1037c into master378 Sep 8, 2026
51 of 53 checks passed
@romanett
romanett deleted the romanett/opc-ua-dotnet-4449-master378 branch September 8, 2026 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1.5.378 Only affects 1.5.378 (pre 2.0) ready Ready to merge once CI Passes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants