Files
lmxopcua/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Calculation/CalculationDriverProbe.cs
T
Joseph Doherty b4a03b4baa fix(calculation): probe JSON options stricter than the real spawn/reinit path (review)
CalculationDriverProbe.Opts (Test-Connect) omitted AllowTrailingCommas and
ReadCommentHandling that CalculationDriverFactoryExtensions.JsonOptions
(spawn) and CalculationDriver.ReinitJsonOptions (in-place ApplyDelta) both
set, so a config blob the real deploy path tolerates could fail Test-Connect
as "invalid JSON" even though deploying it would succeed. Aligned the three
option sets. Also adds CalculationDriverProbeTests.cs, which previously did
not exist at all for this driver type's Test-Connect surface.

Part of code-reviews/Driver.Calculation/findings.md (-003, -004).
2026-08-10 06:59:29 -04:00

52 lines
2.3 KiB
C#

using System.Text.Json;
using System.Text.Json.Serialization;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
namespace ZB.MOM.WW.OtOpcUa.Driver.Calculation;
/// <summary>
/// Test-connect probe for the <c>Calculation</c> pseudo-driver. There is no backend to connect to —
/// the driver computes tags from other tags' values — so the probe just confirms the driver config
/// parses (mini-design §7). Per-script compile verification belongs to the editor diagnostics + the
/// tag editor's inline panel, not the probe (which receives only the driver config). Never throws;
/// returns Ok with negligible latency.
/// </summary>
public sealed class CalculationDriverProbe : IDriverProbe
{
// Mirrors CalculationDriverFactoryExtensions.JsonOptions / CalculationDriver.ReinitJsonOptions
// (AllowTrailingCommas + ReadCommentHandling included) so a config blob the real spawn/reinit path
// tolerates never fails Test-Connect as "invalid JSON" — the probe must never be STRICTER than the
// path it is standing in for.
private static readonly JsonSerializerOptions Opts = new()
{
PropertyNameCaseInsensitive = true,
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
ReadCommentHandling = JsonCommentHandling.Skip,
AllowTrailingCommas = true,
Converters = { new JsonStringEnumConverter() },
};
/// <inheritdoc />
public string DriverType => CalculationDriverFactoryExtensions.DriverTypeName;
/// <inheritdoc />
public Task<DriverProbeResult> ProbeAsync(string configJson, TimeSpan timeout, CancellationToken ct)
{
if (string.IsNullOrWhiteSpace(configJson))
return Task.FromResult(new DriverProbeResult(false, "Config JSON is empty.", null));
try
{
// Parse-only: a Calculation driver's config is well-formed as long as it deserialises to an
// object (the RawTags array is optional — a driver with no calc tags is still valid).
_ = JsonSerializer.Deserialize<CalculationDriverFactoryExtensions.CalculationDriverConfigDto>(configJson, Opts);
}
catch (Exception ex)
{
return Task.FromResult(new DriverProbeResult(false, $"Config JSON is invalid: {ex.Message}", null));
}
return Task.FromResult(new DriverProbeResult(true, null, TimeSpan.Zero));
}
}