fix(opcuaclient): review fixes - drop driver-side OperationLimits chunking (SDK batches), diagnostics as OTel counter, safe discovery selection, options validation at load (#273 #275 #276 #277 #278)

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-08 14:55:53 -04:00
parent 935ba8d1d4
commit 1219b7b13e
13 changed files with 406 additions and 652 deletions
@@ -214,13 +214,6 @@
<label class="form-label">Subscription priority (0-255)</label>
<InputNumber @bind-Value="_form.OpcUa.SubscriptionPriority" @bind-Value:after="EmitAsync" class="form-control form-control-sm" />
</div>
<div class="col-md-3">
<div class="form-check form-switch mt-4">
<InputCheckbox @bind-Value="_form.OpcUa.HonorServerOperationLimits" @bind-Value:after="EmitAsync" class="form-check-input" id="honorOpLimits" />
<label class="form-check-label" for="honorOpLimits">Honor server OperationLimits</label>
</div>
<div class="form-text">Split oversized Read / Write / monitored-item calls.</div>
</div>
<div class="col-md-3">
<div class="form-check form-switch mt-4">
<InputCheckbox @bind-Value="_form.OpcUa.RejectUnknownRevocationStatus" @bind-Value:after="EmitAsync" class="form-check-input" id="rejectUnkRevocation" />
@@ -236,7 +229,12 @@
<div class="col-md-6">
<label class="form-label">Discovery URL (FindServers)</label>
<InputText @bind-Value="_form.OpcUa.DiscoveryUrl" @bind-Value:after="EmitAsync" class="form-control form-control-sm mono" placeholder="opc.tcp://lds:4840" />
<div class="form-text">Optional. Discovered endpoints are tried before the failover list.</div>
<div class="form-text">Optional. Discovered endpoints are tried after the failover list.</div>
</div>
<div class="col-md-6">
<label class="form-label">Discovery server ApplicationUri</label>
<InputText @bind-Value="_form.OpcUa.DiscoveryServerUri" @bind-Value:after="EmitAsync" class="form-control form-control-sm mono" />
<div class="form-text">Required when the discovery server lists more than one server.</div>
</div>
</div>
</div>
@@ -382,10 +380,10 @@
public int SubscriptionLifetimeCount { get; set; } = 1000;
public int SubscriptionMaxNotificationsPerPublish { get; set; }
public int SubscriptionPriority { get; set; }
public bool HonorServerOperationLimits { get; set; } = true;
public bool RejectUnknownRevocationStatus { get; set; }
public string? IssuerStorePath { get; set; }
public string? DiscoveryUrl { get; set; }
public string? DiscoveryServerUri { get; set; }
internal IReadOnlyDictionary<string, string> _unsMappingTable = new Dictionary<string, string>();
@@ -417,10 +415,10 @@
SubscriptionLifetimeCount = (int)Math.Min(r.SubscriptionLifetimeCount, int.MaxValue),
SubscriptionMaxNotificationsPerPublish = (int)Math.Min(r.SubscriptionMaxNotificationsPerPublish, int.MaxValue),
SubscriptionPriority = r.SubscriptionPriority,
HonorServerOperationLimits = r.HonorServerOperationLimits,
RejectUnknownRevocationStatus = r.CertificateValidation.RejectUnknownRevocationStatus,
IssuerStorePath = r.CertificateValidation.IssuerStorePath,
DiscoveryUrl = r.DiscoveryUrl,
DiscoveryServerUri = r.DiscoveryServerUri,
_unsMappingTable = r.UnsMappingTable,
};
@@ -455,13 +453,13 @@
SubscriptionLifetimeCount = (uint)Math.Max(SubscriptionLifetimeCount, 0),
SubscriptionMaxNotificationsPerPublish = (uint)Math.Max(SubscriptionMaxNotificationsPerPublish, 0),
SubscriptionPriority = (byte)Math.Clamp(SubscriptionPriority, 0, 255),
HonorServerOperationLimits = HonorServerOperationLimits,
CertificateValidation = new OpcUaCertificateValidationOptions
{
RejectUnknownRevocationStatus = RejectUnknownRevocationStatus,
IssuerStorePath = string.IsNullOrWhiteSpace(IssuerStorePath) ? null : IssuerStorePath,
},
DiscoveryUrl = string.IsNullOrWhiteSpace(DiscoveryUrl) ? null : DiscoveryUrl,
DiscoveryServerUri = string.IsNullOrWhiteSpace(DiscoveryServerUri) ? null : DiscoveryServerUri,
};
}
}