review(Driver.OpcUaClient): release browse continuation point on cancel
Re-review at 7286d320. -016: BrowseRecursiveAsync now releases the server-side continuation
point on OperationCanceledException (BrowseNext releaseContinuationPoints:true) before
rethrowing (resolves the Browser-002 cross-cutting leak) + TDD.
This commit is contained in:
@@ -934,11 +934,34 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
|
||||
var continuationPoint = result.ContinuationPoint;
|
||||
while (continuationPoint is { Length: > 0 })
|
||||
{
|
||||
var next = await session.BrowseNextAsync(
|
||||
requestHeader: null,
|
||||
releaseContinuationPoints: false,
|
||||
continuationPoints: [continuationPoint],
|
||||
ct: ct).ConfigureAwait(false);
|
||||
BrowseNextResponse next;
|
||||
try
|
||||
{
|
||||
next = await session.BrowseNextAsync(
|
||||
requestHeader: null,
|
||||
releaseContinuationPoints: false,
|
||||
continuationPoints: [continuationPoint],
|
||||
ct: ct).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// Caller cancelled mid-pagination. Release the server-side cursor so it
|
||||
// doesn't hold resources until session close (Driver.OpcUaClient-016;
|
||||
// same pattern as Driver.OpcUaClient.Browser-002). Use CancellationToken.None
|
||||
// for the release — the original token is already cancelled so we must not
|
||||
// gate the release on it. Fire-and-forget: if the server is also unreachable,
|
||||
// the release fails silently and the cursor times out server-side anyway.
|
||||
try
|
||||
{
|
||||
await session.BrowseNextAsync(
|
||||
requestHeader: null,
|
||||
releaseContinuationPoints: true,
|
||||
continuationPoints: [continuationPoint],
|
||||
ct: CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
catch { /* best-effort — server may have already cleaned up */ }
|
||||
throw;
|
||||
}
|
||||
|
||||
if (next.Results.Count == 0) break;
|
||||
var nextResult = next.Results[0];
|
||||
@@ -947,6 +970,12 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
|
||||
continuationPoint = nextResult.ContinuationPoint;
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// Propagate cancellation — don't silently swallow it like a transient browse
|
||||
// failure. The caller's CancellationToken was honoured; let it observe that.
|
||||
throw;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Transient browse failure on a sub-tree — don't kill the whole discovery, just
|
||||
|
||||
Reference in New Issue
Block a user