Skip to content

Commit cb9da03

Browse files
fix(eventcounter): deduplicate events by ID in BigQuery count queries
BigQuery has no primary keys, so an at-least-once Pub/Sub redelivery after a successful append stores the same event twice. The MySQL and Postgres event tables reject duplicates via PRIMARY KEY (id), but the BigQuery count queries trusted row uniqueness: - evaluation_count.sql used COUNT(id) for the event total, so a duplicated evaluation event inflated evaluationTotal forever. - goal_count.sql aggregated COUNT(id) and SUM(value) per user directly over the raw table, so duplicates inflated goalTotal and the per-user value sums that feed the Bayesian value-metric analysis. User counts (COUNT(DISTINCT user_id)) and therefore the CVR analysis were already duplicate-tolerant. Deduplicate by event ID: COUNT(DISTINCT id) for the evaluation total, and a DISTINCT-by-ID CTE in the goal query before any aggregation. Each legitimate event has its own unique ID, so repeat evaluations/goals by the same user are still counted. This also retroactively corrects duplicates already stored in the tables. This is also what made TestGrpcExperimentResult hang in the dev cluster: the test waits for exact event counts, and a single duplicated event kept the count above the expected total forever. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 6afb699 commit cb9da03

2 files changed

Lines changed: 26 additions & 8 deletions

File tree

pkg/eventcounter/storage/v2/dwh_database/bigquery/sql/evaluation_count.sql

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
SELECT
22
variation_id as variationID,
33
COUNT(DISTINCT user_id) as evaluationUser,
4-
COUNT(id) as evaluationTotal
4+
-- DISTINCT by event ID: BigQuery has no primary keys, so an at-least-once
5+
-- Pub/Sub redelivery can append the same event twice. Each legitimate
6+
-- event has its own unique ID, so this still counts repeat evaluations
7+
-- by the same user.
8+
COUNT(DISTINCT id) as evaluationTotal
59
FROM
610
`%s`
711
WHERE

pkg/eventcounter/storage/v2/dwh_database/bigquery/sql/goal_count.sql

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
WITH grouped_by_user_evaluation AS (
2-
SELECT
1+
WITH deduped_events AS (
2+
-- BigQuery has no primary keys, so an at-least-once Pub/Sub redelivery
3+
-- can append the same event twice. Deduplicate by event ID before any
4+
-- aggregation, otherwise duplicates inflate event_count and value_sum.
5+
-- Duplicates are identical rows, so DISTINCT over the used columns is
6+
-- equivalent to picking one row per ID.
7+
SELECT DISTINCT
8+
id,
39
user_id,
410
variation_id,
5-
COUNT(id) as event_count,
6-
IFNULL(SUM(value), 0) as value_sum
11+
value
712
FROM
813
`%s`
914
WHERE
@@ -12,9 +17,18 @@ WITH grouped_by_user_evaluation AS (
1217
AND goal_id = @goalID
1318
AND feature_id = @featureID
1419
AND feature_version = @featureVersion
15-
GROUP BY
16-
user_id,
17-
variation_id
20+
),
21+
grouped_by_user_evaluation AS (
22+
SELECT
23+
user_id,
24+
variation_id,
25+
COUNT(id) as event_count,
26+
IFNULL(SUM(value), 0) as value_sum
27+
FROM
28+
deduped_events
29+
GROUP BY
30+
user_id,
31+
variation_id
1832
),
1933
cap_level AS (
2034
-- Winsorization threshold: the configurable percentile

0 commit comments

Comments
 (0)