using ZB.MOM.WW.OtOpcUa.Commons.Interfaces; using ZB.MOM.WW.OtOpcUa.Commons.Messages.Admin; namespace ZB.MOM.WW.OtOpcUa.AdminUI.Clients; /// /// Thin AdminUI-side wrapper for the Test Connect operation. Dispatches a /// through IAdminOperationsClient, applies a /// 65-second outer wall (the actor itself clamps to [1,60]s; this guards against the /// Ask never replying), and surfaces a friendly result for the Razor button to render. /// public sealed class AdminProbeService { private readonly IAdminOperationsClient _client; /// Initializes a new instance of the . /// The admin operations client used to dispatch probe requests. public AdminProbeService(IAdminOperationsClient client) => _client = client; /// /// Dispatches a Test Connect probe for the supplied driver type and config JSON, /// waiting up to 65 seconds for a reply before surfacing a timeout failure. /// /// Driver type key (must match an installed IDriverProbe.DriverType). /// Driver config as JSON (same shape as DriverInstance.DriverConfig). /// Per-probe timeout; actor clamps to [1, 60]. /// Optional cancellation token from the caller. public async Task TestAsync( string driverType, string configJson, int timeoutSeconds, CancellationToken ct = default) { var correlationId = Guid.NewGuid(); var msg = new TestDriverConnect(driverType, configJson, timeoutSeconds, correlationId); // 65s outer guard — the actor's CTS clamps to 60s; if the Ask never returns we still want // a deterministic failure surface for the UI. using var outerCts = CancellationTokenSource.CreateLinkedTokenSource(ct); outerCts.CancelAfter(TimeSpan.FromSeconds(65)); try { return await _client.AskAsync(msg, outerCts.Token); } catch (OperationCanceledException) { return new TestDriverConnectResult(false, "Probe request did not return within 65s.", null, correlationId); } catch (Exception ex) { return new TestDriverConnectResult(false, $"Probe dispatch failed: {ex.Message}", null, correlationId); } } }