Merge branch 'worktree-agent-a7084b23177344196' into arch-review-remediation
This commit is contained in:
@@ -317,9 +317,19 @@ still replied while the outer Asks are still waiting.
|
||||
A central `SiteAuditReconciliationActor` periodically (default 5 min per site)
|
||||
asks each site for its oldest `Pending` row and pending count; if backlog is
|
||||
non-draining (e.g., telemetry actor wedged), central issues a
|
||||
`PullAuditEvents(sinceUtc, batchSize)` and inserts-if-not-exists. Accepted rows
|
||||
are flipped to `ForwardState = 'Reconciled'` site-side. Same self-healing
|
||||
pattern as Site Call Audit's reconciliation of `SiteCalls`.
|
||||
`PullAuditEvents(sinceUtc, batchSize[, afterId])` and inserts-if-not-exists.
|
||||
Same self-healing pattern as Site Call Audit's reconciliation of `SiteCalls`.
|
||||
|
||||
**The pull is at-least-once (WP2.3).** Serving a row is not proof that central
|
||||
received it, so rows are **not** flipped when they are served. The site flips
|
||||
`ForwardState = 'Reconciled'` for everything at or before the cursor carried by
|
||||
the **next** pull — the only evidence central actually consumed them
|
||||
(`ISiteAuditQueue.MarkReconciledUpToAsync`, run before the read so retired rows
|
||||
do not consume the batch budget). A fault between the response leaving the site
|
||||
and central committing it therefore re-serves the batch instead of losing it;
|
||||
central dedups on `EventId`, so a re-ship is a no-op. Previously the site flipped
|
||||
each served batch immediately, and a central-side fault in that window dropped
|
||||
those rows permanently — `ReadPendingSinceAsync` would never return them again.
|
||||
|
||||
**Endpoint resolution & NodeB failover.** Each pull dials the site's `NodeA`
|
||||
gRPC address first; if `NodeA` is blank the site's `NodeB` address becomes the
|
||||
@@ -333,13 +343,21 @@ mapping/unexpected fault collapses to empty without a second dial (the other
|
||||
node would hit the same fault). The same resolution + failover applies to Site
|
||||
Call Audit's `PullSiteCalls`.
|
||||
|
||||
> **Cursor keyset (tracked follow-up).** The `PullAuditEvents` cursor is still a
|
||||
> single `sinceUtc` timestamp. Site Call Audit's pull now uses a composite
|
||||
> `(UpdatedAtUtc, TrackedOperationId)` keyset to avoid a single-timestamp pin
|
||||
> (see Component-SiteCallAudit.md → Reconciliation). The same keyset should be
|
||||
> applied here, but it is lower urgency because the audit cursor already re-pulls
|
||||
> idempotently on `EventId` — a saturated single-timestamp window re-inserts
|
||||
> harmless no-ops rather than losing rows.
|
||||
**Cursor keyset.** The site side of the composite `(OccurredAtUtc, EventId)`
|
||||
keyset now exists (WP2.3): `PullAuditEventsRequest.after_id` (additive field 3)
|
||||
mirrors `PullSiteCallsRequest.after_id`, and `ISiteAuditQueue.ReadPendingSinceAsync`
|
||||
switches from the inclusive `OccurredAtUtc >= since` to a strict composite
|
||||
comparison when it is set, so a burst sharing one instant drains via the id
|
||||
tiebreak instead of pinning the cursor.
|
||||
|
||||
> **Central still sends a bare timestamp (tracked follow-up).**
|
||||
> `IPullAuditEventsClient`/`SiteAuditReconciliationActor` do not yet populate
|
||||
> `after_id`, so today's cursor remains a single `sinceUtc` under the legacy
|
||||
> inclusive read. Two consequences, both benign: a window whose rows all share one
|
||||
> instant re-serves rather than advancing (idempotent on `EventId`, as before), and
|
||||
> the rows **at** the cursor instant cannot be proven received, so they stay
|
||||
> servable until a newer row moves the cursor. Wiring `after_id` at central makes
|
||||
> the retirement exact; the site accepts it already.
|
||||
|
||||
### Central direct-write (central-originated events)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user