fix(opcuaclient): don't count idle-session BadNoSubscription as a publish error (lmxopcua#764)
v2-ci / unit-tests (push) Has been cancelled
v2-ci / unit-tests (push) Has been cancelled
The SDK keeps sending publish requests on a session that holds no subscription, and the server answers each with an anonymous (id 0) BadNoSubscription. With nothing tracked there is nothing to lose, but every answer was counted on publish_error, so the counter climbed on any idle driver. HandlePublishError now returns before counting for an anonymous BadNoSubscription while neither the data nor the alarm subscription set tracks anything. Any other PublishError, and an anonymous one while something is tracked, is counted and handled as before. Not addressed from #764: the Republish/state probe for a delete slower than the 5 s grace, and the #728 wire test's fixed delays. Tests: OpcUaClientIdlePublishErrorTests (idle session: not counted, with a BadTooManyPublishRequests positive control; tracked subscription: still counted). The idle test fails without the fix. Driver.OpcUaClient.Tests 295/0. Docs: drivers/OpcUaClient.md. Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
@@ -3377,7 +3377,9 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Session PublishError: always counted; a BadNoSubscription / BadSubscriptionIdInvalid naming a
|
||||
/// Session PublishError: counted, except an anonymous BadNoSubscription while the driver tracks no
|
||||
/// subscription at all (#764) — the SDK keeps publishing on a session with none, and the server's answer is
|
||||
/// idle noise, not an error. A BadNoSubscription / BadSubscriptionIdInvalid naming a
|
||||
/// subscription the driver tracks means the server dropped it while the session lived. An anonymous
|
||||
/// BadNoSubscription means the server holds none at all — a loss of anything tracked, except within
|
||||
/// <see cref="StaleNoSubscriptionGrace"/> of the driver deleting its last subscription (#763).
|
||||
@@ -3387,6 +3389,15 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
|
||||
|
||||
private void HandlePublishError(object? sender, StatusCode code, uint subscriptionId)
|
||||
{
|
||||
// #764: with nothing tracked there is nothing to lose, and the SDK's publish loop keeps asking a session
|
||||
// that holds no subscription — every answer is an anonymous BadNoSubscription. Counting those made
|
||||
// publish_error climb on every idle driver; they are neither counted nor acted on.
|
||||
if (code == StatusCodes.BadNoSubscription && subscriptionId == 0
|
||||
&& _subscriptions.IsEmpty && _alarmSubscriptions.IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_diag.Record(OpcUaClientDiagnostics.PublishError);
|
||||
var generation = Volatile.Read(ref _lifecycleGeneration);
|
||||
if (sender is not null && !ReferenceEquals(sender, Session)) return;
|
||||
|
||||
Reference in New Issue
Block a user