fix(site-call-audit): reconciliation pull serves only un-acked tracking rows (node-local ack ledger), batched page upsert, prune removed sites' cursors (review 2026-10-21 06/PERF-2 + lane H follow-up)

This commit is contained in:
Joseph Doherty
2026-10-22 09:35:30 -04:00
parent e69be1654f
commit 88273693f9
12 changed files with 789 additions and 10 deletions
@@ -416,6 +416,54 @@ public class SiteAuditTelemetryActorTests : TestKit
Assert.Equal(expectedIds, emittedEventIds);
}
/// <summary>
/// Verifies that the tracking-row versions central ACCEPTED are recorded as central acks
/// in the tracking store — and only those — so the SiteCalls reconciliation pull stops
/// re-serving them (review 2026-10-21 06/PERF-2).
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task CachedDrain_AcceptedPackets_AreRecordedAsCentralAcks()
{
var acceptedRow = NewCachedEvent(AuditKind.CachedSubmit);
var refusedRow = NewCachedEvent(AuditKind.CachedSubmit);
_queue.ReadPendingAsync(Arg.Any<int>(), Arg.Any<CancellationToken>())
.Returns(Task.FromResult<IReadOnlyList<AuditEvent>>(Array.Empty<AuditEvent>()));
_queue.ReadPendingCachedTelemetryAsync(Arg.Any<int>(), Arg.Any<CancellationToken>())
.Returns(
Task.FromResult<IReadOnlyList<AuditEvent>>(new[] { acceptedRow, refusedRow }),
Task.FromResult<IReadOnlyList<AuditEvent>>(Array.Empty<AuditEvent>()));
var acceptedTid = new TrackedOperationId(acceptedRow.CorrelationId!.Value);
var refusedTid = new TrackedOperationId(refusedRow.CorrelationId!.Value);
var acceptedSnapshot = NewSnapshot(acceptedTid) with
{
UpdatedAtUtc = new DateTime(2026, 5, 20, 10, 0, 7, DateTimeKind.Utc),
};
_trackingStore.GetStatusAsync(acceptedTid, Arg.Any<CancellationToken>())
.Returns(Task.FromResult<TrackingStatusSnapshot?>(acceptedSnapshot));
_trackingStore.GetStatusAsync(refusedTid, Arg.Any<CancellationToken>())
.Returns(Task.FromResult<TrackingStatusSnapshot?>(NewSnapshot(refusedTid)));
_client.IngestCachedTelemetryAsync(Arg.Any<CachedTelemetryBatch>(), Arg.Any<CancellationToken>())
.Returns(_ =>
{
var ack = new IngestAck();
ack.AcceptedEventIds.Add(acceptedRow.EventId.ToString());
return Task.FromResult(ack);
});
CreateActorWithCachedDrain();
await AwaitAssertAsync(async () =>
{
await _trackingStore.Received(1).RecordCentralAcksAsync(
Arg.Is<IReadOnlyDictionary<TrackedOperationId, DateTime>>(d =>
d.Count == 1 && d[acceptedTid] == acceptedSnapshot.UpdatedAtUtc),
Arg.Any<CancellationToken>());
}, TimeSpan.FromSeconds(5));
}
/// <summary>Verifies that a cached row with no tracking snapshot past the grace period is abandoned while a valid row still flows.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]