fix(core-abstractions): resolve Low code-review findings (Core.Abstractions-004,005,006,007,008)
- Core.Abstractions-004: guard DriverTypeRegistry.Register with a Lock so concurrent registrations are atomic. - Core.Abstractions-005: narrow PollGroupEngine catch blocks to non-fatal exceptions, add optional onError callback, tolerate disposed-CTS races. - Core.Abstractions-006: document the deliberate int-vs-uint asymmetry on IHistoryProvider.ReadEventsAsync / IHistorianDataSource.ReadEventsAsync. - Core.Abstractions-007: pin the gaps with PollGroupEngine + DriverHealth contract tests. - Core.Abstractions-008: correct XML docs on DriverHealth.LastError and the optional / required asymmetry on the history-read surfaces. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,14 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||
/// Galaxy (Wonderware Historian via the optional plugin), OPC UA Client (forward
|
||||
/// to upstream server).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="ReadAtTimeAsync"/> and <see cref="ReadEventsAsync"/> are C# default interface
|
||||
/// methods that throw <see cref="NotSupportedException"/> — drivers opt in by overriding so
|
||||
/// a raw-only driver compiles without forcing it to provide at-time / event surfaces it
|
||||
/// has no backend for. The sibling server-side surface, <see cref="IHistorianDataSource"/>,
|
||||
/// declares both methods as required because a registered historian owns the full read
|
||||
/// surface; the asymmetry is intentional (Core.Abstractions-008).
|
||||
/// </remarks>
|
||||
public interface IHistoryProvider
|
||||
{
|
||||
/// <summary>
|
||||
@@ -60,12 +68,24 @@ public interface IHistoryProvider
|
||||
/// </param>
|
||||
/// <param name="startUtc">Inclusive lower bound on <c>EventTimeUtc</c>.</param>
|
||||
/// <param name="endUtc">Exclusive upper bound on <c>EventTimeUtc</c>.</param>
|
||||
/// <param name="maxEvents">Upper cap on returned events — the driver's backend enforces this.</param>
|
||||
/// <param name="maxEvents">
|
||||
/// Upper cap on returned events — the driver's backend enforces this. The type is
|
||||
/// <see cref="int"/> rather than <see cref="uint"/> (which the sibling raw / processed
|
||||
/// reads use for <c>maxValuesPerNode</c>) because callers and downstream historian
|
||||
/// adapters historically treat <c>maxEvents <= 0</c> as a sentinel meaning
|
||||
/// "use the backend's default cap" (see <c>WonderwareHistorianClient</c> /
|
||||
/// <c>HistorianDataSource</c>). The asymmetry is intentional — Core.Abstractions-006.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">Request cancellation.</param>
|
||||
/// <remarks>
|
||||
/// Default implementation throws. Only drivers with an event historian (Galaxy via the
|
||||
/// Wonderware Alarm & Events log) override. Modbus / the OPC UA Client driver stay
|
||||
/// with the default and let callers see <c>BadHistoryOperationUnsupported</c>.
|
||||
///
|
||||
/// Note the type asymmetry with <see cref="ReadRawAsync"/> /
|
||||
/// <see cref="ReadProcessedAsync"/> (both use <c>uint maxValuesPerNode</c>): event
|
||||
/// readers accept a signed <c>int maxEvents</c> so callers can pass 0 / negative as a
|
||||
/// "use default cap" sentinel without an extra parameter or overload.
|
||||
/// </remarks>
|
||||
Task<HistoricalEventsResult> ReadEventsAsync(
|
||||
string? sourceName,
|
||||
|
||||
Reference in New Issue
Block a user