From c78f33850c817029543fe1d5f5c70b31f291096f Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Apr 2026 18:00:09 +0000 Subject: [PATCH] Exclude stem downloads from track download counts The per-track and per-user-total download count queries matched every track_downloads row by parent_track_id alone, so for an original track each stem download (which shares the same parent_track_id but has a different track_id) was counted as an additional download of the original. Require d.track_id = t.track_id in both queries so only the actual original-track download rows contribute to the count; stem tracks keep counting their own stem-specific rows as before. https://claude.ai/code/session_01M8ZDgw87vg9S2weug8Jj9P --- api/dbv1/get_track_download_counts.sql.go | 11 +++++--- ...get_user_track_download_count_total.sql.go | 4 +-- .../queries/get_track_download_counts.sql | 11 +++++--- .../get_user_track_download_count_total.sql | 4 +-- api/v1_track_download_count_test.go | 26 ++++++++++++++----- 5 files changed, 38 insertions(+), 18 deletions(-) diff --git a/api/dbv1/get_track_download_counts.sql.go b/api/dbv1/get_track_download_counts.sql.go index 4e05d54b..5afd34e6 100644 --- a/api/dbv1/get_track_download_counts.sql.go +++ b/api/dbv1/get_track_download_counts.sql.go @@ -15,10 +15,13 @@ SELECT ( SELECT count(*)::bigint FROM track_downloads d - WHERE (t.stem_of IS NOT NULL - AND d.parent_track_id = (t.stem_of->>'parent_track_id')::int - AND d.track_id = t.track_id) - OR (t.stem_of IS NULL AND d.parent_track_id = t.track_id) + WHERE d.track_id = t.track_id + AND ( + (t.stem_of IS NOT NULL + AND d.parent_track_id = (t.stem_of->>'parent_track_id')::int) + OR (t.stem_of IS NULL + AND d.parent_track_id = t.track_id) + ) ) AS download_count FROM tracks t WHERE t.track_id = ANY($1::int[]) diff --git a/api/dbv1/get_user_track_download_count_total.sql.go b/api/dbv1/get_user_track_download_count_total.sql.go index 1855bd60..19a8a3b6 100644 --- a/api/dbv1/get_user_track_download_count_total.sql.go +++ b/api/dbv1/get_user_track_download_count_total.sql.go @@ -18,11 +18,11 @@ WHERE EXISTS ( WHERE t.owner_id = $1 AND t.is_current = true AND t.is_delete = false + AND d.track_id = t.track_id AND ( (t.stem_of IS NULL AND d.parent_track_id = t.track_id) OR (t.stem_of IS NOT NULL - AND (t.stem_of->>'parent_track_id')::int = d.parent_track_id - AND d.track_id = t.track_id) + AND (t.stem_of->>'parent_track_id')::int = d.parent_track_id) ) ) ` diff --git a/api/dbv1/queries/get_track_download_counts.sql b/api/dbv1/queries/get_track_download_counts.sql index c1c5eb0a..d209c1f3 100644 --- a/api/dbv1/queries/get_track_download_counts.sql +++ b/api/dbv1/queries/get_track_download_counts.sql @@ -4,10 +4,13 @@ SELECT ( SELECT count(*)::bigint FROM track_downloads d - WHERE (t.stem_of IS NOT NULL - AND d.parent_track_id = (t.stem_of->>'parent_track_id')::int - AND d.track_id = t.track_id) - OR (t.stem_of IS NULL AND d.parent_track_id = t.track_id) + WHERE d.track_id = t.track_id + AND ( + (t.stem_of IS NOT NULL + AND d.parent_track_id = (t.stem_of->>'parent_track_id')::int) + OR (t.stem_of IS NULL + AND d.parent_track_id = t.track_id) + ) ) AS download_count FROM tracks t WHERE t.track_id = ANY(@track_ids::int[]) diff --git a/api/dbv1/queries/get_user_track_download_count_total.sql b/api/dbv1/queries/get_user_track_download_count_total.sql index 8c2d2447..6ed1910f 100644 --- a/api/dbv1/queries/get_user_track_download_count_total.sql +++ b/api/dbv1/queries/get_user_track_download_count_total.sql @@ -9,10 +9,10 @@ WHERE EXISTS ( WHERE t.owner_id = @user_id AND t.is_current = true AND t.is_delete = false + AND d.track_id = t.track_id AND ( (t.stem_of IS NULL AND d.parent_track_id = t.track_id) OR (t.stem_of IS NOT NULL - AND (t.stem_of->>'parent_track_id')::int = d.parent_track_id - AND d.track_id = t.track_id) + AND (t.stem_of->>'parent_track_id')::int = d.parent_track_id) ) ); diff --git a/api/v1_track_download_count_test.go b/api/v1_track_download_count_test.go index 774b154b..f7bf1cb8 100644 --- a/api/v1_track_download_count_test.go +++ b/api/v1_track_download_count_test.go @@ -17,10 +17,16 @@ func TestV1TrackDownloadCount(t *testing.T) { ctx := context.Background() require.NotNil(t, app.writePool, "test requires write pool") - // Track 200 is "Culca Canyon" (eYJyn). Insert two download rows so download_count is 2. + // Track 200 is "Culca Canyon" (eYJyn). Insert two original-track download rows + // plus two stem download rows (same parent_track_id, different track_id). + // Only the originals should be counted. _, err := app.writePool.Exec(ctx, ` INSERT INTO track_downloads (txhash, blocknumber, parent_track_id, track_id, user_id) - VALUES ('tx-dl-1', 101, 200, 200, 1), ('tx-dl-2', 101, 200, 200, 2) + VALUES + ('tx-dl-1', 101, 200, 200, 1), + ('tx-dl-2', 101, 200, 200, 2), + ('tx-dl-stem-1', 101, 200, 9001, 1), + ('tx-dl-stem-2', 101, 200, 9002, 1) `) require.NoError(t, err) @@ -37,10 +43,14 @@ func TestV1TracksDownloadCounts(t *testing.T) { ctx := context.Background() require.NotNil(t, app.writePool, "test requires write pool") - // Track 200 (eYJyn) gets 2 downloads; track 201 (eYZmn) has none. + // Track 200 (eYJyn) gets 2 original-track downloads plus a stem download that + // should be ignored; track 201 (eYZmn) has none. _, err := app.writePool.Exec(ctx, ` INSERT INTO track_downloads (txhash, blocknumber, parent_track_id, track_id, user_id) - VALUES ('tx-dl-1', 101, 200, 200, 1), ('tx-dl-2', 101, 200, 200, 2) + VALUES + ('tx-dl-1', 101, 200, 200, 1), + ('tx-dl-2', 101, 200, 200, 2), + ('tx-dl-stem-1', 101, 200, 9001, 1) `) require.NoError(t, err) @@ -64,10 +74,14 @@ func TestV1UserTracksDownloadCount(t *testing.T) { ctx := context.Background() require.NotNil(t, app.writePool, "test requires write pool") - // Track 200 (eYJyn) is owned by user 2. Insert two download rows. + // Track 200 (eYJyn) is owned by user 2. Insert two original-track download rows + // plus a stem download row that should be excluded from the total. _, err := app.writePool.Exec(ctx, ` INSERT INTO track_downloads (txhash, blocknumber, parent_track_id, track_id, user_id) - VALUES ('tx-user-total-1', 101, 200, 200, 1), ('tx-user-total-2', 101, 200, 200, 2) + VALUES + ('tx-user-total-1', 101, 200, 200, 1), + ('tx-user-total-2', 101, 200, 200, 2), + ('tx-user-total-stem-1', 101, 200, 9001, 1) `) require.NoError(t, err)