refactor(playlists): SQL queries return top-5 candidate seeds
For-You + Songs-Like-X seed selection moves to Go-side daily rotation (next commit). The SQL change just widens the candidate pool: top-5 played tracks instead of single top played track; top-5 artists instead of top-3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -308,7 +308,7 @@ SELECT p.artist_id,
|
|||||||
FROM plays p
|
FROM plays p
|
||||||
LEFT JOIN liked l ON l.artist_id = p.artist_id
|
LEFT JOIN liked l ON l.artist_id = p.artist_id
|
||||||
ORDER BY score DESC, p.artist_id
|
ORDER BY score DESC, p.artist_id
|
||||||
LIMIT 3
|
LIMIT 5
|
||||||
`
|
`
|
||||||
|
|
||||||
type PickSeedArtistsRow struct {
|
type PickSeedArtistsRow struct {
|
||||||
@@ -316,7 +316,10 @@ type PickSeedArtistsRow struct {
|
|||||||
Score int64
|
Score int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Top-3 most-engaged distinct artists in the user's last 7 days.
|
// Top-5 most-engaged distinct artist candidates in the user's last 7
|
||||||
|
// days. The Go-side picker (pickSeedArtistsForDay) shuffles these
|
||||||
|
// daily-deterministically and takes the first 3 so the set of
|
||||||
|
// "Songs like X" mixes rotates day-to-day.
|
||||||
// Score = unskipped-play count + 5 if user has liked the artist.
|
// Score = unskipped-play count + 5 if user has liked the artist.
|
||||||
func (q *Queries) PickSeedArtists(ctx context.Context, userID pgtype.UUID) ([]PickSeedArtistsRow, error) {
|
func (q *Queries) PickSeedArtists(ctx context.Context, userID pgtype.UUID) ([]PickSeedArtistsRow, error) {
|
||||||
rows, err := q.db.Query(ctx, pickSeedArtists, userID)
|
rows, err := q.db.Query(ctx, pickSeedArtists, userID)
|
||||||
@@ -408,7 +411,7 @@ func (q *Queries) PickTopPlayedTrackForArtistByUser(ctx context.Context, arg Pic
|
|||||||
return id, err
|
return id, err
|
||||||
}
|
}
|
||||||
|
|
||||||
const pickTopPlayedTrackForUser = `-- name: PickTopPlayedTrackForUser :one
|
const pickTopPlayedTracksForUser = `-- name: PickTopPlayedTracksForUser :many
|
||||||
SELECT t.id
|
SELECT t.id
|
||||||
FROM play_events pe
|
FROM play_events pe
|
||||||
JOIN tracks t ON t.id = pe.track_id
|
JOIN tracks t ON t.id = pe.track_id
|
||||||
@@ -417,16 +420,33 @@ SELECT t.id
|
|||||||
AND pe.was_skipped = false
|
AND pe.was_skipped = false
|
||||||
GROUP BY t.id
|
GROUP BY t.id
|
||||||
ORDER BY COUNT(*) DESC, t.id
|
ORDER BY COUNT(*) DESC, t.id
|
||||||
LIMIT 1
|
LIMIT 5
|
||||||
`
|
`
|
||||||
|
|
||||||
// For-You seed selection. Returns the user's most-played non-skipped
|
// For-You candidate seeds. Returns the user's top-5 most-played
|
||||||
// track in the last 7 days; tie-break by track_id for determinism.
|
// non-skipped tracks in the last 7 days; tie-break by track_id for
|
||||||
func (q *Queries) PickTopPlayedTrackForUser(ctx context.Context, userID pgtype.UUID) (pgtype.UUID, error) {
|
// determinism. The Go-side picker (pickForYouSeedForDay) chooses one
|
||||||
row := q.db.QueryRow(ctx, pickTopPlayedTrackForUser, userID)
|
// of the returned rows as today's seed via userIDHash so the
|
||||||
var id pgtype.UUID
|
// candidate pool rotates day-to-day while staying stable within a
|
||||||
err := row.Scan(&id)
|
// day.
|
||||||
return id, err
|
func (q *Queries) PickTopPlayedTracksForUser(ctx context.Context, userID pgtype.UUID) ([]pgtype.UUID, error) {
|
||||||
|
rows, err := q.db.Query(ctx, pickTopPlayedTracksForUser, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []pgtype.UUID
|
||||||
|
for rows.Next() {
|
||||||
|
var id pgtype.UUID
|
||||||
|
if err := rows.Scan(&id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, id)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const tryClaimSystemPlaylistRun = `-- name: TryClaimSystemPlaylistRun :one
|
const tryClaimSystemPlaylistRun = `-- name: TryClaimSystemPlaylistRun :one
|
||||||
|
|||||||
@@ -47,7 +47,10 @@ UPDATE system_playlist_runs
|
|||||||
UPDATE system_playlist_runs SET in_flight = false WHERE in_flight = true;
|
UPDATE system_playlist_runs SET in_flight = false WHERE in_flight = true;
|
||||||
|
|
||||||
-- name: PickSeedArtists :many
|
-- name: PickSeedArtists :many
|
||||||
-- Top-3 most-engaged distinct artists in the user's last 7 days.
|
-- Top-5 most-engaged distinct artist candidates in the user's last 7
|
||||||
|
-- days. The Go-side picker (pickSeedArtistsForDay) shuffles these
|
||||||
|
-- daily-deterministically and takes the first 3 so the set of
|
||||||
|
-- "Songs like X" mixes rotates day-to-day.
|
||||||
-- Score = unskipped-play count + 5 if user has liked the artist.
|
-- Score = unskipped-play count + 5 if user has liked the artist.
|
||||||
WITH plays AS (
|
WITH plays AS (
|
||||||
SELECT t.artist_id,
|
SELECT t.artist_id,
|
||||||
@@ -67,11 +70,15 @@ SELECT p.artist_id,
|
|||||||
FROM plays p
|
FROM plays p
|
||||||
LEFT JOIN liked l ON l.artist_id = p.artist_id
|
LEFT JOIN liked l ON l.artist_id = p.artist_id
|
||||||
ORDER BY score DESC, p.artist_id
|
ORDER BY score DESC, p.artist_id
|
||||||
LIMIT 3;
|
LIMIT 5;
|
||||||
|
|
||||||
-- name: PickTopPlayedTrackForUser :one
|
-- name: PickTopPlayedTracksForUser :many
|
||||||
-- For-You seed selection. Returns the user's most-played non-skipped
|
-- For-You candidate seeds. Returns the user's top-5 most-played
|
||||||
-- track in the last 7 days; tie-break by track_id for determinism.
|
-- non-skipped tracks in the last 7 days; tie-break by track_id for
|
||||||
|
-- determinism. The Go-side picker (pickForYouSeedForDay) chooses one
|
||||||
|
-- of the returned rows as today's seed via userIDHash so the
|
||||||
|
-- candidate pool rotates day-to-day while staying stable within a
|
||||||
|
-- day.
|
||||||
SELECT t.id
|
SELECT t.id
|
||||||
FROM play_events pe
|
FROM play_events pe
|
||||||
JOIN tracks t ON t.id = pe.track_id
|
JOIN tracks t ON t.id = pe.track_id
|
||||||
@@ -80,7 +87,7 @@ SELECT t.id
|
|||||||
AND pe.was_skipped = false
|
AND pe.was_skipped = false
|
||||||
GROUP BY t.id
|
GROUP BY t.id
|
||||||
ORDER BY COUNT(*) DESC, t.id
|
ORDER BY COUNT(*) DESC, t.id
|
||||||
LIMIT 1;
|
LIMIT 5;
|
||||||
|
|
||||||
-- name: PickTopPlayedTrackForArtistByUser :one
|
-- name: PickTopPlayedTrackForArtistByUser :one
|
||||||
-- "Songs like X" seed selection. Returns the user's most-played non-skipped
|
-- "Songs like X" seed selection. Returns the user's most-played non-skipped
|
||||||
|
|||||||
Reference in New Issue
Block a user