Merge branch 'worktree-agent-a7084b23177344196' into arch-review-remediation
This commit is contained in:
@@ -109,10 +109,47 @@ public interface ISiteAuditQueue
|
||||
/// </remarks>
|
||||
/// <param name="sinceUtc">Lower bound timestamp (UTC).</param>
|
||||
/// <param name="batchSize">Maximum number of rows to return.</param>
|
||||
/// <param name="afterId">
|
||||
/// Composite-keyset tiebreak cursor (WP2.3), mirroring
|
||||
/// <see cref="IOperationTrackingStore.ReadChangedSinceAsync"/>: when non-null it is the
|
||||
/// <see cref="AuditEvent.EventId"/> ("D" GUID form) of the last row already consumed at
|
||||
/// <paramref name="sinceUtc"/>, and only rows strictly after the composite
|
||||
/// <c>(OccurredAtUtc, EventId)</c> pair are returned — so a burst sharing one exact
|
||||
/// instant drains via the id tiebreak instead of pinning the inclusive-timestamp cursor.
|
||||
/// Null (the first pull, or a central that never sets it) keeps the inclusive
|
||||
/// <c>>=</c> contract.
|
||||
/// </param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>A task that resolves to audit events at or after <paramref name="sinceUtc"/> in pending or forwarded state, up to <paramref name="batchSize"/>.</returns>
|
||||
Task<IReadOnlyList<AuditEvent>> ReadPendingSinceAsync(
|
||||
DateTime sinceUtc, int batchSize, CancellationToken ct = default);
|
||||
DateTime sinceUtc, int batchSize, string? afterId = null, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Reconciliation-pull commit surface, cursor form (WP2.3): flips every row at or before
|
||||
/// the composite cursor <c>(<paramref name="sinceUtc"/>, <paramref name="afterId"/>)</c>
|
||||
/// from <see cref="ZB.MOM.WW.ScadaBridge.Commons.Types.Enums.AuditForwardState.Pending"/>/
|
||||
/// <see cref="ZB.MOM.WW.ScadaBridge.Commons.Types.Enums.AuditForwardState.Forwarded"/> to
|
||||
/// <see cref="ZB.MOM.WW.ScadaBridge.Commons.Types.Enums.AuditForwardState.Reconciled"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The cursor is central's proof of receipt: it only advances past rows central has
|
||||
/// actually ingested. Flipping on THAT — rather than on having merely served the rows —
|
||||
/// is what makes the pull at-least-once: a fault between the response leaving the site
|
||||
/// and central committing it leaves the rows unflipped, so the next pull re-serves them
|
||||
/// (central dedups on <see cref="AuditEvent.EventId"/>).
|
||||
/// <para>
|
||||
/// With <paramref name="afterId"/> null the cursor is a bare timestamp under the legacy
|
||||
/// inclusive <c>>=</c> read contract, so only rows STRICTLY older than
|
||||
/// <paramref name="sinceUtc"/> are proven received; rows at the boundary instant are left
|
||||
/// alone. Idempotent; already-Reconciled rows are untouched.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="sinceUtc">The cursor timestamp central has consumed up to (UTC).</param>
|
||||
/// <param name="afterId">The last consumed <see cref="AuditEvent.EventId"/> at that instant, or null.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>A task that resolves to the number of rows flipped.</returns>
|
||||
Task<int> MarkReconciledUpToAsync(
|
||||
DateTime sinceUtc, string? afterId, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Reconciliation-pull commit surface: flips the supplied EventIds to
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.DebugView;
|
||||
|
||||
/// <summary>
|
||||
/// Asks one instance for a point-in-time <see cref="DebugViewSnapshot"/>.
|
||||
/// </summary>
|
||||
/// <param name="InstanceUniqueName">Unique name of the instance to snapshot.</param>
|
||||
/// <param name="CorrelationId">Correlation id echoed on the reply.</param>
|
||||
/// <param name="AlarmsOnly">
|
||||
/// When <c>true</c> the site builds ONLY the alarm half of the snapshot and returns an
|
||||
/// empty <see cref="DebugViewSnapshot.AttributeValues"/> list (wire efficiency, WP2.3).
|
||||
/// Set by the central per-site live alarm cache, whose seed/reconcile fan-out discards
|
||||
/// every attribute row anyway. Defaults to <c>false</c> so the Debug View and every other
|
||||
/// caller keep the full snapshot; additive on the wire
|
||||
/// (<c>DebugSnapshotRequestDto.alarms_only</c>, field 3).
|
||||
/// </param>
|
||||
public record DebugSnapshotRequest(
|
||||
string InstanceUniqueName,
|
||||
string CorrelationId);
|
||||
string CorrelationId,
|
||||
bool AlarmsOnly = false);
|
||||
|
||||
@@ -64,6 +64,35 @@ public static class ScadaBridgeTelemetry
|
||||
Meter.CreateCounter<long>("scadabridge.site.alarm_cache.reconnects", unit: "1",
|
||||
description: "Live-alarm aggregator site-wide gRPC stream reconnects (NodeA↔NodeB flip or reconcile-driven reopen).");
|
||||
|
||||
/// <summary>
|
||||
/// Incremented for each live delta evicted from a per-site live-alarm aggregator's
|
||||
/// bounded pre-seed buffer (drop-oldest, WP2.3). Non-zero means a seed/reconcile
|
||||
/// fan-out ran long enough for the delta storm behind it to exceed the cap — the
|
||||
/// dropped transitions are recovered by the fan-out's authoritative snapshot, but a
|
||||
/// sustained climb points at a slow site.
|
||||
/// </summary>
|
||||
private static readonly Counter<long> _liveAlarmBufferDrops =
|
||||
Meter.CreateCounter<long>("scadabridge.site.alarm_cache.buffer_dropped", unit: "1",
|
||||
description: "Live deltas evicted from a live-alarm aggregator's bounded pre-seed buffer (drop-oldest).");
|
||||
|
||||
/// <summary>
|
||||
/// Incremented for each debug event evicted from a central debug session's bounded
|
||||
/// pre-snapshot buffer (drop-oldest, WP2.3). The Debug View is lossy-under-backpressure
|
||||
/// by design; this makes the loss measurable instead of unbounded memory growth.
|
||||
/// </summary>
|
||||
private static readonly Counter<long> _debugPreSnapshotDrops =
|
||||
Meter.CreateCounter<long>("scadabridge.central.debug_view.presnapshot_dropped", unit: "1",
|
||||
description: "Debug events evicted from a central debug session's bounded pre-snapshot buffer (drop-oldest).");
|
||||
|
||||
/// <summary>
|
||||
/// Incremented for each event evicted from a site-hosted gRPC stream's bounded send
|
||||
/// channel, tagged by stream kind (<c>instance</c> = Debug View, <c>site-alarms</c> =
|
||||
/// the site-wide alarm feed behind the operator Alarm Summary).
|
||||
/// </summary>
|
||||
private static readonly Counter<long> _siteStreamEventDrops =
|
||||
Meter.CreateCounter<long>("scadabridge.site.stream.events_dropped", unit: "1",
|
||||
description: "Events evicted from a site gRPC stream's bounded send channel, tagged by stream kind.");
|
||||
|
||||
// ---------------- Observable gauges ----------------
|
||||
|
||||
/// <summary>Current count of open site connections, mutated via <see cref="Interlocked"/>.</summary>
|
||||
@@ -136,6 +165,19 @@ public static class ScadaBridgeTelemetry
|
||||
/// <summary>Records that a per-site live-alarm aggregator re-established its site-wide gRPC stream.</summary>
|
||||
public static void RecordLiveAlarmStreamReconnect() => _liveAlarmStreamReconnects.Add(1);
|
||||
|
||||
/// <summary>Records live deltas evicted from a live-alarm aggregator's bounded pre-seed buffer.</summary>
|
||||
/// <param name="count">Number of deltas evicted.</param>
|
||||
public static void RecordLiveAlarmBufferDrop(long count = 1) => _liveAlarmBufferDrops.Add(count);
|
||||
|
||||
/// <summary>Records debug events evicted from a debug session's bounded pre-snapshot buffer.</summary>
|
||||
/// <param name="count">Number of events evicted.</param>
|
||||
public static void RecordDebugPreSnapshotDrop(long count = 1) => _debugPreSnapshotDrops.Add(count);
|
||||
|
||||
/// <summary>Records an event evicted from a site gRPC stream's bounded send channel.</summary>
|
||||
/// <param name="streamKind">Stream kind tag (<c>instance</c> or <c>site-alarms</c>).</param>
|
||||
public static void RecordSiteStreamEventDropped(string streamKind) =>
|
||||
_siteStreamEventDrops.Add(1, new KeyValuePair<string, object?>("stream", streamKind));
|
||||
|
||||
/// <summary>
|
||||
/// Registers the provider the StoreAndForward queue-depth gauge reads on each observation.
|
||||
/// A later task supplies a provider that reads the real StoreAndForward depth. A null
|
||||
|
||||
Reference in New Issue
Block a user