feat(historian): HistoryRead override (Raw/Processed/AtTime) over IHistorianDataSource
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// A no-op <see cref="IHistorianDataSource"/> — the server's default historian backend when no
|
||||
/// real historian has been registered. Every read returns an EMPTY result (no samples / events,
|
||||
/// null continuation point) so the node-manager's HistoryRead override surfaces
|
||||
/// <c>GoodNoData</c> for a historized node rather than faulting, and
|
||||
/// <see cref="GetHealthSnapshot"/> reports a fully-disabled (zeroed, disconnected) snapshot.
|
||||
/// <para>
|
||||
/// A process-wide singleton via <see cref="Instance"/> (private ctor): it carries no state
|
||||
/// and is immutable, so one shared instance is safe to assign as the node-manager's
|
||||
/// <c>HistorianDataSource</c> default until the Host wires a real source post-start (Task 5).
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public sealed class NullHistorianDataSource : IHistorianDataSource
|
||||
{
|
||||
/// <summary>The shared singleton instance.</summary>
|
||||
public static readonly NullHistorianDataSource Instance = new();
|
||||
|
||||
private static readonly HistoryReadResult EmptyRead = new(Array.Empty<DataValueSnapshot>(), null);
|
||||
private static readonly HistoricalEventsResult EmptyEvents = new(Array.Empty<HistoricalEvent>(), null);
|
||||
|
||||
private NullHistorianDataSource()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<HistoryReadResult> ReadRawAsync(
|
||||
string fullReference,
|
||||
DateTime startUtc,
|
||||
DateTime endUtc,
|
||||
uint maxValuesPerNode,
|
||||
CancellationToken cancellationToken) => Task.FromResult(EmptyRead);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<HistoryReadResult> ReadProcessedAsync(
|
||||
string fullReference,
|
||||
DateTime startUtc,
|
||||
DateTime endUtc,
|
||||
TimeSpan interval,
|
||||
HistoryAggregateType aggregate,
|
||||
CancellationToken cancellationToken) => Task.FromResult(EmptyRead);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<HistoryReadResult> ReadAtTimeAsync(
|
||||
string fullReference,
|
||||
IReadOnlyList<DateTime> timestampsUtc,
|
||||
CancellationToken cancellationToken) => Task.FromResult(EmptyRead);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<HistoricalEventsResult> ReadEventsAsync(
|
||||
string? sourceName,
|
||||
DateTime startUtc,
|
||||
DateTime endUtc,
|
||||
int maxEvents,
|
||||
CancellationToken cancellationToken) => Task.FromResult(EmptyEvents);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a fully-disabled snapshot — no connections open, every counter zero, every nullable
|
||||
/// field null, no cluster nodes. Pure; never blocks.
|
||||
/// </summary>
|
||||
public HistorianHealthSnapshot GetHealthSnapshot() => new(
|
||||
TotalQueries: 0,
|
||||
TotalSuccesses: 0,
|
||||
TotalFailures: 0,
|
||||
ConsecutiveFailures: 0,
|
||||
LastSuccessTime: null,
|
||||
LastFailureTime: null,
|
||||
LastError: null,
|
||||
ProcessConnectionOpen: false,
|
||||
EventConnectionOpen: false,
|
||||
ActiveProcessNode: null,
|
||||
ActiveEventNode: null,
|
||||
Nodes: Array.Empty<HistorianClusterNodeState>());
|
||||
|
||||
/// <summary>No-op — the null source owns no unmanaged resources.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
// Stateless singleton; nothing to release.
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user