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:
@@ -271,6 +271,9 @@ public class SiteAuditTelemetryActor : ReceiveActor
|
||||
var batch = new CachedTelemetryBatch();
|
||||
var wireBytes = AuditWireBudget.InitialBytes;
|
||||
var emittedEventIds = new List<Guid>(pending.Count);
|
||||
// EventId → the tracking-row version its packet carried, so an accepted
|
||||
// packet can be recorded as a central ack (review 2026-10-21 06/PERF-2).
|
||||
var packetVersions = new Dictionary<Guid, (TrackedOperationId Id, DateTime UpdatedAtUtc)>(pending.Count);
|
||||
// Rows whose operational half can never be built. They are marked
|
||||
// PushAbandoned so they LEAVE this queue — see AbandonUnresolvableAsync
|
||||
// for why that is safe and why leaving them Pending is not.
|
||||
@@ -338,6 +341,7 @@ public class SiteAuditTelemetryActor : ReceiveActor
|
||||
var packet = BuildCachedPacket(auditRow, snapshot);
|
||||
if (!AuditWireBudget.TryAppend(batch.Packets, packet, ref wireBytes, auditRow.EventId.ToString())) break;
|
||||
emittedEventIds.Add(auditRow.EventId);
|
||||
packetVersions[auditRow.EventId] = (snapshot.Id, snapshot.UpdatedAtUtc);
|
||||
}
|
||||
|
||||
if (lookupFailures > 0)
|
||||
@@ -389,6 +393,7 @@ public class SiteAuditTelemetryActor : ReceiveActor
|
||||
{
|
||||
await _queue.MarkForwardedAsync(acceptedIds, ct)
|
||||
.ConfigureAwait(false);
|
||||
await RecordCentralAcksAsync(acceptedIds, packetVersions, ct).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await RecordRefusalsAsync(
|
||||
@@ -413,6 +418,51 @@ public class SiteAuditTelemetryActor : ReceiveActor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tells the tracking store which tracking-row versions central has just accepted, so
|
||||
/// the SiteCalls reconciliation pull stops re-serving them (review 2026-10-21
|
||||
/// 06/PERF-2). Accepted means central committed the packet's <c>SiteCalls</c> upsert
|
||||
/// in the same transaction as its audit row, i.e. central now holds exactly what a pull
|
||||
/// of that version would send. Several packets of one operation in a batch collapse to
|
||||
/// the newest version. Best-effort: the store only enqueues, and a failure here just
|
||||
/// leaves the rows eligible for one more pull.
|
||||
/// </summary>
|
||||
private async Task RecordCentralAcksAsync(
|
||||
IReadOnlyList<Guid> acceptedIds,
|
||||
Dictionary<Guid, (TrackedOperationId Id, DateTime UpdatedAtUtc)> packetVersions,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var versions = new Dictionary<TrackedOperationId, DateTime>();
|
||||
foreach (var eventId in acceptedIds)
|
||||
{
|
||||
if (!packetVersions.TryGetValue(eventId, out var v))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!versions.TryGetValue(v.Id, out var existing) || v.UpdatedAtUtc > existing)
|
||||
{
|
||||
versions[v.Id] = v.UpdatedAtUtc;
|
||||
}
|
||||
}
|
||||
|
||||
if (versions.Count == 0 || _trackingStore is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await _trackingStore.RecordCentralAcksAsync(versions, ct).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) when (ex is not OperationCanceledException)
|
||||
{
|
||||
_logger.LogDebug(ex,
|
||||
"Recording {Count} central ack(s) in the tracking store failed; those rows stay eligible for the reconciliation pull.",
|
||||
versions.Count);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves cached rows whose operational half can never be built out of the
|
||||
/// cached-drain queue, as <see cref="SiteAuditForwardStates.PushAbandoned"/>.
|
||||
|
||||
Reference in New Issue
Block a user