Skip to main content
← Back to list
01Issue
BugOpenSwamp Club
AssigneesNone

Relationships

⊘ blocks #929↔ sibling #925

#927 Activity projector runs on both telemetry replicas — same-day chunks can double-grant (grant_id collides but granted_at differs, ReplacingMergeTree never dedups)

Opened by keeb · 7/2/2026

Found during #925 planning (adversarial review of the projector stage).

Setup: prod telemetry-api runs 2 replicas, and SCORE_GRANTS_CUTOVER is set at the deployment level — so startActivityProjector (services/telemetry/main.ts:110) runs on BOTH replicas, each on its own unsynchronized 60s tick. Same for startIdentityMapSync (harmless there — ReplacingMergeTree, duplicate work only).

The race: activity-asof-projector.sql is one INSERT INTO swamp.score_grants ... SELECT whose granted CTE reads current units_before from the ledger. Two replicas whose ticks overlap can both read the same units_before for a grain and both insert a chunk with the SAME deterministic grant_id (keyed on units_before). For PAST days that's fine — granted_at = toDateTime64(day) is deterministic, so the ReplacingMergeTree key (distinct_id, granted_at, grant_id) collapses them. But TODAY's chunks carry granted_at = now64(3), which differs per replica → both rows survive FINAL → the amount is counted twice, permanently (next tick sees units_before doubled and the cnt > units_before guard just goes quiet — no clawback, the inflation sticks).

Why it hasn't bitten (visibly) yet: the race window is one overlapping tick at low event volume; today's figura parity check (1510=1510) predates much concurrency. It gets more likely as volume grows.

Fix directions (pick one):

  1. Single-runner gate: Mongo lease/leader election so only one replica projects (the trace_control polling infra shows the desired-state pattern; a TTL lease doc is enough), or split the projector into its own single-replica deployment.
  2. Make granted_at deterministic for today's chunks too (e.g. derive from (day, units_before)) so the RMT key collapses duplicates — but that changes the 'live stamp moment' semantics the council wanted.

Blocks the parity gate for the #925 Stage-5 projector work — should land before or with it. Related: epic #847.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED

Open

7/2/2026, 9:45:10 PM

No activity in this phase yet.

03Sludge Pulse
keeb linked related to #9257/2/2026, 9:57:21 PM
keeb linked blocked by #9297/2/2026, 9:57:23 PM

Sign in to post a ripple.