mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-18 14:43:08 +08:00
Fix MetricsAreEmittedForReconnectAndGateWaitAsync race on fast runners
CI failure (AzDO build 14553 log 874, net48 Windows): the test asserted that opcua.channel.reconnect.duration was emitted but only saw the attempts / gate.wait / open / active measurements. Root cause: race in the TEST (production behavior is correct). ChannelEntry.RunReconnectCycleAsync records RecordReconnectAttempt BEFORE calling tcs.TrySetResult(true), but RecordReconnectDuration is invoked in the finally block AFTER TrySetResult returns control. The test awaits the reconnect task — which completes on TrySetResult — and then immediately asserts both metrics. On a fast net48 runner the test thread reaches the duration assertion before the finally block runs, so the histogram measurement is missing. Add a WaitForMeasurementAsync helper that polls for the duration measurement with a 2-second budget before the existing hard assertion fires. The hard assertion is preserved so the test still fails if the metric is genuinely never emitted. Verified locally: net48 5/5 runs pass (was 0/1 in CI), net10 1/1 (no regression).
This commit is contained in:
@@ -773,6 +773,17 @@ namespace Opc.Ua.Client.Tests.Stack.Client
|
||||
|
||||
await Task.WhenAll(reconnectTask, sendTask).ConfigureAwait(false);
|
||||
|
||||
// RunReconnectCycleAsync.RecordReconnectDuration is emitted from a
|
||||
// finally block AFTER tcs.TrySetResult(true) returns, so on a fast
|
||||
// runner the test thread can race past the assertion before the
|
||||
// measurement lands. Poll briefly for the histogram measurement.
|
||||
await WaitForMeasurementAsync(
|
||||
metrics,
|
||||
"opcua.channel.reconnect.duration",
|
||||
Tag("endpoint", endpointUrl),
|
||||
Tag("outcome", "success"))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
Assert.That(metrics.HasMeasurement(
|
||||
"opcua.channel.reconnect.attempts",
|
||||
Tag("endpoint", endpointUrl),
|
||||
@@ -793,6 +804,21 @@ namespace Opc.Ua.Client.Tests.Stack.Client
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task WaitForMeasurementAsync(
|
||||
ChannelMetricListener metrics,
|
||||
string instrumentName,
|
||||
params KeyValuePair<string, object?>[] tags)
|
||||
{
|
||||
const int kMaxPollMs = 2000;
|
||||
const int kPollIntervalMs = 25;
|
||||
int elapsed = 0;
|
||||
while (!metrics.HasMeasurement(instrumentName, tags) && elapsed < kMaxPollMs)
|
||||
{
|
||||
await Task.Delay(kPollIntervalMs).ConfigureAwait(false);
|
||||
elapsed += kPollIntervalMs;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[NonParallelizable]
|
||||
public async Task ActivitySpanIsRecordedForReconnectAsync()
|
||||
|
||||
Reference in New Issue
Block a user