Files
lmxopcua/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/ClientTelemetry.cs
T
Joseph Doherty 826312befe docs: fill missing XML docs and strip tracking IDs from src comments
Clears CommentChecker findings in src/ (3,280 -> 209, the remainder being false
positives like PLC-5/IEEE-754/M0.0) by adding missing summaries/params/returns,
normalising inheritdoc usage, and removing Gitea/review tracking IDs while keeping
the rationale they annotated. Comment-only: comment-stripped sources are identical
to the parent commit.
2026-10-15 06:14:58 -04:00

47 lines
2.1 KiB
C#

using Opc.Ua;
namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
/// <summary>
/// The one <see cref="ITelemetryContext" /> the shared client hands the SDK's non-obsolete (telemetry-taking)
/// overloads. An empty builder keeps SDK internals off any logging provider; the client logs through Serilog.
/// </summary>
internal static class ClientTelemetry
{
private static readonly Lazy<ITelemetryContext> Instance = new(() => DefaultTelemetry.Create(_ => { }));
/// <summary>Gets the shared telemetry context.</summary>
public static ITelemetryContext Context => Instance.Value;
}
/// <summary>
/// Bounded sync-over-async for the <c>Dispose</c> paths, which cannot await. Runs on the thread pool so a
/// caller on a synchronization context (the Avalonia UI thread) cannot deadlock, and waits at most
/// <see cref="Timeout" /> so a dead server cannot hang teardown.
/// </summary>
internal static class DisposeBridge
{
private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(5);
/// <summary>Runs <paramref name="work" /> to completion (or the timeout), swallowing every failure.</summary>
/// <param name="work">The asynchronous work to run; it receives a token that is cancelled when the timeout elapses.</param>
public static void Run(Func<CancellationToken, Task> work)
{
using var cts = new CancellationTokenSource(Timeout);
try
{
var task = Task.Run(() => work(cts.Token), cts.Token);
// Observe a late fault so it never surfaces as an unobserved-task exception.
_ = task.ContinueWith(t => _ = t.Exception, TaskContinuationOptions.OnlyOnFaulted);
// The CTS's own timer and this Wait race: when Wait loses, `using` would dispose the CTS before
// the token ever fired, leaving the work running while the caller goes on to dispose the session.
// Cancel explicitly so the in-flight Close/Delete is told to stop.
if (!task.Wait(Timeout)) { cts.Cancel(); }
}
catch
{
// Teardown is best-effort, exactly as the synchronous Close/Delete it replaces.
}
}
}