feat(sitecallaudit): PullSiteCalls reconciliation plumbing (store read + RPC + site handler + central client)
Site Call Audit (#22): build the documented periodic reconciliation PULL self-heal path for the eventually-consistent central SiteCalls mirror, as a dedicated PullSiteCalls gRPC RPC kept separate from the audit pull. This is the pull PLUMBING only; the central reconciliation tick is a separate follow-up. - IOperationTrackingStore.ReadChangedSinceAsync(sinceUtc, batchSize): inclusive UpdatedAtUtc cursor, oldest-first, batch-capped; SQLite impl projects tracking rows onto SiteCallOperational (Kind->Channel, TargetSummary->Target, SourceSite left empty - the store has no site-id column). - sitestream.proto: rpc PullSiteCalls + PullSiteCallsRequest/Response, mirroring PullAuditEvents; regenerated checked-in SiteStreamGrpc/*.cs. - SiteCallDtoMapper.ToDto(SiteCallOperational): inverse of FromDto for the handler. - SiteStreamGrpcServer.PullSiteCalls handler + SetOperationTrackingStore seam; Host wires the seam alongside SetSiteAuditQueue (site roles only). - Central IPullSiteCallsClient + GrpcPullSiteCallsClient (home: AuditLog/Central to reuse ISiteEnumerator; SiteCallAudit does not reference AuditLog). Re-stamps SourceSite from the dialed siteId; no-throw on tolerable transport faults; SpecifyKind (not ToUniversalTime) cursor handling. Central-only DI registration. Tests: ReadChangedSinceAsync (4), PullSiteCalls handler (6), GrpcPullSiteCallsClient (8). Full solution build 0 warnings/0 errors (TreatWarningsAsErrors).
This commit is contained in:
@@ -118,4 +118,40 @@ public interface IOperationTrackingStore
|
||||
Task PurgeTerminalAsync(
|
||||
DateTime olderThanUtc,
|
||||
CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Reconciliation read (Site Call Audit #22): return tracking rows whose
|
||||
/// <c>UpdatedAtUtc</c> is at or after <paramref name="sinceUtc"/> as
|
||||
/// <see cref="SiteCallOperational"/> projections, ordered by
|
||||
/// <c>UpdatedAtUtc</c> ascending and capped at <paramref name="batchSize"/>.
|
||||
/// This is the site-side feed for central's <c>PullSiteCalls</c> RPC — the
|
||||
/// documented periodic self-heal pull that backfills the eventually-consistent
|
||||
/// central <c>SiteCalls</c> mirror when best-effort push telemetry is lost.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The lower bound is inclusive so a caller can resume from the last
|
||||
/// returned <c>UpdatedAtUtc</c> without skipping a row that shares that
|
||||
/// instant; central ingest is insert-if-not-exists then upsert-on-newer, so
|
||||
/// re-reading the boundary row is a harmless no-op. The oldest-first cap lets
|
||||
/// the caller advance the cursor monotonically across follow-up pulls.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <see cref="SiteCallOperational.SourceSite"/> is left as the empty string:
|
||||
/// the site id is not a tracking-store column, and the central client re-stamps
|
||||
/// it from the <c>siteId</c> it dialed (the only authority that knows which
|
||||
/// site the rows came from). <see cref="SiteCallOperational.Channel"/> is
|
||||
/// projected from the row's <c>Kind</c> (<c>DbWriteCached → DbOutbound</c>,
|
||||
/// otherwise <c>ApiOutbound</c>) and <see cref="SiteCallOperational.Target"/>
|
||||
/// from <c>TargetSummary</c>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="sinceUtc">Inclusive lower bound on <c>UpdatedAtUtc</c>; <see cref="DateTime.MinValue"/> reads from the start.</param>
|
||||
/// <param name="batchSize">Maximum number of rows to return (oldest first).</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>The matching rows projected to <see cref="SiteCallOperational"/>, oldest-first, capped at <paramref name="batchSize"/>.</returns>
|
||||
Task<IReadOnlyList<SiteCallOperational>> ReadChangedSinceAsync(
|
||||
DateTime sinceUtc,
|
||||
int batchSize,
|
||||
CancellationToken ct = default);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Integration;
|
||||
|
||||
/// <summary>
|
||||
/// Site Call Audit (#22) periodic reconciliation pull response: the next batch of
|
||||
/// site cached-call operational rows (the eventually-consistent <c>SiteCalls</c>
|
||||
/// mirror's self-heal feed) plus a <paramref name="MoreAvailable"/> flag signalling
|
||||
/// the caller to advance the watermark and pull again. Mirrors
|
||||
/// <see cref="PullAuditEventsResponse"/>; carries the central <see cref="SiteCall"/>
|
||||
/// entity the ingest path upserts. See Component-SiteCallAudit.md.
|
||||
/// </summary>
|
||||
/// <param name="SiteCalls">The next batch of operational rows, ordered oldest-first by <see cref="SiteCall.UpdatedAtUtc"/>.</param>
|
||||
/// <param name="MoreAvailable">True when the site saturated the requested batch size — the caller should advance the cursor and pull again.</param>
|
||||
public sealed record PullSiteCallsResponse(
|
||||
IReadOnlyList<SiteCall> SiteCalls,
|
||||
bool MoreAvailable);
|
||||
Reference in New Issue
Block a user