feat(historian-gateway): FasterLog historization outbox (PerEntry/Periodic, drop-oldest)
Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions.Historian;
|
||||
|
||||
/// <summary>
|
||||
/// Per-append durability cadence for the historization outbox. Local to the OtOpcUa abstraction
|
||||
/// layer (deliberately decoupled from the gateway's internal store-forward commit-mode type).
|
||||
/// </summary>
|
||||
public enum HistorizationCommitMode
|
||||
{
|
||||
/// <summary>fsync the log before each <c>AppendAsync</c> returns — safest, no loss window.</summary>
|
||||
PerEntry,
|
||||
|
||||
/// <summary>Batch commits onto a background timer — higher throughput, a bounded worst-case loss window.</summary>
|
||||
Periodic,
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions.Historian;
|
||||
|
||||
/// <summary>
|
||||
/// One durable record buffered by the continuous-historization outbox before it is written to
|
||||
/// the historian. Carries the minimal payload the SQL analog live-value write path can ingest:
|
||||
/// a numeric value, a quality code, and a UTC timestamp keyed by tag.
|
||||
/// </summary>
|
||||
/// <param name="Id">Stable identifier used to ack (remove) the entry once written. Unique per append.</param>
|
||||
/// <param name="Tag">Fully-qualified historian tag name the value is recorded against.</param>
|
||||
/// <param name="NumericValue">The coerced numeric sample value (the SQL write path is numeric-only).</param>
|
||||
/// <param name="Quality">OPC-UA-derived quality code (e.g. 192 = Good) carried through to the historian.</param>
|
||||
/// <param name="TimestampUtc">UTC source timestamp of the sample.</param>
|
||||
public sealed record HistorizationOutboxEntry(
|
||||
Guid Id,
|
||||
string Tag,
|
||||
double NumericValue,
|
||||
ushort Quality,
|
||||
DateTime TimestampUtc);
|
||||
@@ -0,0 +1,40 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions.Historian;
|
||||
|
||||
/// <summary>
|
||||
/// Durable, crash-safe FIFO buffer the continuous-historization recorder appends sampled values
|
||||
/// to <em>before</em> acking the writer, so nothing is lost if the process dies mid-drain. An
|
||||
/// implementation guarantees: appended entries survive an unclean restart up to its commit
|
||||
/// cadence; <see cref="PeekBatchAsync"/> returns entries in append (FIFO) order; and
|
||||
/// <see cref="RemoveAsync"/> durably reclaims an acked entry. A capacity-bounded implementation
|
||||
/// drops the oldest entry on overflow and reflects it in <see cref="DroppedCount"/>.
|
||||
/// </summary>
|
||||
public interface IHistorizationOutbox : IDisposable
|
||||
{
|
||||
/// <summary>Lifetime count of entries dropped because an append would have exceeded capacity.</summary>
|
||||
long DroppedCount { get; }
|
||||
|
||||
/// <summary>Appends <paramref name="entry"/> to the tail of the durable buffer.</summary>
|
||||
/// <param name="entry">The value record to buffer.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
ValueTask AppendAsync(HistorizationOutboxEntry entry, CancellationToken ct);
|
||||
|
||||
/// <summary>
|
||||
/// Returns up to <paramref name="max"/> oldest un-acked entries in FIFO order without removing
|
||||
/// them. Removal happens via <see cref="RemoveAsync"/> once each entry is durably written.
|
||||
/// </summary>
|
||||
/// <param name="max">Maximum number of entries to return; must be positive.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
ValueTask<IReadOnlyList<HistorizationOutboxEntry>> PeekBatchAsync(int max, CancellationToken ct);
|
||||
|
||||
/// <summary>
|
||||
/// Durably removes the entry identified by <paramref name="id"/> (and any older entries ahead
|
||||
/// of it in FIFO order), advancing the buffer head. A no-op when the id is unknown.
|
||||
/// </summary>
|
||||
/// <param name="id">The <see cref="HistorizationOutboxEntry.Id"/> to ack.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
ValueTask RemoveAsync(Guid id, CancellationToken ct);
|
||||
|
||||
/// <summary>Current number of un-acked entries held in the buffer.</summary>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
ValueTask<int> CountAsync(CancellationToken ct);
|
||||
}
|
||||
Reference in New Issue
Block a user