fix(site-call-audit): composite keyset cursor eliminates the single-timestamp reconciliation pin; pinned state now a published event
Reconciliation cursor becomes composite (UpdatedAtUtc, TrackedOperationId); IPullSiteCallsClient/GrpcPullSiteCallsClient forward the Task-15 after_id keyset (additive param, null preserves the legacy inclusive >= contract). A burst sharing one exact UpdatedAtUtc now drains via the id tiebreak instead of pinning forever. A legacy site that ignores after_id is latched + published as SiteCallReconciliationPinnedChanged on the EventStream (transition-only), replacing the prior silent log line.
This commit is contained in:
@@ -80,6 +80,7 @@ public sealed class GrpcPullSiteCallsClient : IPullSiteCallsClient
|
||||
public async Task<PullSiteCallsResponse> PullAsync(
|
||||
string siteId,
|
||||
DateTime sinceUtc,
|
||||
string? afterId,
|
||||
int batchSize,
|
||||
CancellationToken ct)
|
||||
{
|
||||
@@ -100,6 +101,10 @@ public sealed class GrpcPullSiteCallsClient : IPullSiteCallsClient
|
||||
// EnsureUtc keeps Timestamp.FromDateTime happy (it requires UTC kind).
|
||||
SinceUtc = Timestamp.FromDateTime(EnsureUtc(sinceUtc)),
|
||||
BatchSize = batchSize,
|
||||
// Composite-keyset tiebreak (Task 16). proto3 has no nullable string —
|
||||
// an unset/empty AfterId is the site's signal to keep the legacy
|
||||
// inclusive-timestamp contract (also what a first pull sends).
|
||||
AfterId = afterId ?? string.Empty,
|
||||
};
|
||||
|
||||
ProtoPullResponse reply;
|
||||
|
||||
@@ -46,12 +46,22 @@ public interface IPullSiteCallsClient
|
||||
/// </summary>
|
||||
/// <param name="siteId">The identifier of the site to pull cached-call operational rows from.</param>
|
||||
/// <param name="sinceUtc">Only rows with an <c>UpdatedAtUtc</c> at or after this cursor time are returned.</param>
|
||||
/// <param name="afterId">
|
||||
/// The composite-keyset tiebreak cursor (Task 16). When non-null it is the
|
||||
/// <c>TrackedOperationId</c> of the last row already consumed at
|
||||
/// <paramref name="sinceUtc"/>; the site returns only rows strictly greater
|
||||
/// than the composite <c>(UpdatedAtUtc, TrackedOperationId)</c> pair, so a
|
||||
/// burst sharing one exact <c>UpdatedAtUtc</c> drains via the id tiebreak
|
||||
/// instead of pinning the inclusive-timestamp cursor. Null on the first pull
|
||||
/// (or against a legacy site) preserves the inclusive <c>>=</c> contract.
|
||||
/// </param>
|
||||
/// <param name="batchSize">Maximum number of rows to return per call.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>A task that resolves to the next reconciliation batch with a <c>MoreAvailable</c> flag.</returns>
|
||||
Task<PullSiteCallsResponse> PullAsync(
|
||||
string siteId,
|
||||
DateTime sinceUtc,
|
||||
string? afterId,
|
||||
int batchSize,
|
||||
CancellationToken ct);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user