Files
MrAlaskan 565fc02535 fix(subscription): fail transfer synchronization when deleting stale monitored items (#4031)
### Summary

This PR makes `MonitoredItemManager.TrySynchronizeHandlesAsync()` treat
`DeleteMonitoredItems` failures as transfer-synchronization failures and
adds a regression test that verifies the client no longer reports
success when the server rejects deletion of stale monitored items.

### Problem

OPC UA Part 4 requires clients to evaluate service results at two
levels: `ResponseHeader.ServiceResult` reports the outcome of the
service call as a whole. `Results[]` reports the outcome of each
individual operation in that service. Even when the service-level result
is `Good`, the service may still have only partially succeeded. The
client therefore still needs to inspect the response payload, especially
the per-operation `StatusCode` values, before concluding that the
requested work actually completed.

In `TrySynchronizeHandlesAsync()`, the transfer/recovery path deletes
monitored items that still exist on the server but no longer exist
locally. Previously, this delete path treated
`DeleteMonitoredItemsAsync()` as successful as long as the call itself
did not throw, and it did not validate `ResponseHeader.ServiceResult`,
`Results[]`, or the associated diagnostic information. As a result, the
client could report transfer synchronization success even when the
server explicitly returned failures for one or more stale monitored
items.

### Changes

- Validate the `DeleteMonitoredItemsAsync()` response inside
`TrySynchronizeHandlesAsync()` instead of treating any non-throwing call
as success.
- Return `false` when the delete operation reports a bad service-level
result or any bad per-item result, so synchronization only succeeds
after stale server-side items are actually removed.
- Add a regression test that verifies `TryCompleteTransferAsync()`
returns `false` when deletion of an extraneous server-side monitored
item is rejected.
2026-07-20 06:17:21 +02:00
..