feat(db): add M6a rediscover queries (albums + artists, with fallbacks)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 09:00:20 -04:00
parent 10c84a536e
commit 5ed3c20b74
2 changed files with 350 additions and 0 deletions
+92
View File
@@ -253,3 +253,95 @@ LEFT JOIN LATERAL (
) cnt ON true
ORDER BY max_started.started_at DESC, a.id
LIMIT $2;
-- name: ListRediscoverAlbumsForUser :many
-- M6a: albums liked >30 days ago AND not played in the last 14 days,
-- ordered by longest-since-last-play first. The HAVING clause uses an
-- epoch sentinel so albums with NO plays count as eligible (their
-- "last play" is treated as 1970, which is always >14 days ago).
WITH eligible AS (
SELECT al.id AS album_id,
gla.liked_at,
max(pe.started_at) AS last_played
FROM general_likes_albums gla
JOIN albums al ON al.id = gla.album_id
LEFT JOIN tracks t ON t.album_id = al.id
LEFT JOIN play_events pe ON pe.track_id = t.id AND pe.user_id = $1
WHERE gla.user_id = $1
AND gla.liked_at < now() - interval '30 days'
GROUP BY al.id, gla.liked_at
HAVING COALESCE(max(pe.started_at), '1970-01-01'::timestamptz)
< now() - interval '14 days'
)
SELECT sqlc.embed(albums), artists.name AS artist_name
FROM eligible e
JOIN albums ON albums.id = e.album_id
JOIN artists ON artists.id = albums.artist_id
ORDER BY (now() - COALESCE(e.last_played, e.liked_at)) DESC, albums.id
LIMIT $2;
-- name: ListRediscoverAlbumsFallbackForUser :many
-- M6a: random sample of liked albums for the user. The Go service uses
-- this to top up the rediscover row when ListRediscoverAlbumsForUser
-- returns fewer than `limit` rows.
SELECT sqlc.embed(albums), artists.name AS artist_name
FROM general_likes_albums gla
JOIN albums ON albums.id = gla.album_id
JOIN artists ON artists.id = albums.artist_id
WHERE gla.user_id = $1
ORDER BY random()
LIMIT $2;
-- name: ListRediscoverArtistsForUser :many
-- M6a: artists liked >30 days ago AND none of their tracks played in the
-- last 14 days, ordered by longest-since-last-play. cover_album_id is
-- derived from a representative album (LEFT JOIN LATERAL).
WITH eligible AS (
SELECT a.id AS artist_id,
gla.liked_at,
max(pe.started_at) AS last_played
FROM general_likes_artists gla
JOIN artists a ON a.id = gla.artist_id
LEFT JOIN tracks t ON t.artist_id = a.id
LEFT JOIN play_events pe ON pe.track_id = t.id AND pe.user_id = $1
WHERE gla.user_id = $1
AND gla.liked_at < now() - interval '30 days'
GROUP BY a.id, gla.liked_at
HAVING COALESCE(max(pe.started_at), '1970-01-01'::timestamptz)
< now() - interval '14 days'
)
SELECT sqlc.embed(artists),
cov.id AS cover_album_id,
cnt.album_count::bigint AS album_count
FROM eligible e
JOIN artists ON artists.id = e.artist_id
LEFT JOIN LATERAL (
SELECT id FROM albums
WHERE artist_id = artists.id AND cover_art_path IS NOT NULL
ORDER BY created_at DESC LIMIT 1
) cov ON true
LEFT JOIN LATERAL (
SELECT count(*) AS album_count
FROM albums WHERE artist_id = artists.id
) cnt ON true
ORDER BY (now() - COALESCE(e.last_played, e.liked_at)) DESC, artists.id
LIMIT $2;
-- name: ListRediscoverArtistsFallbackForUser :many
SELECT sqlc.embed(artists),
cov.id AS cover_album_id,
cnt.album_count::bigint AS album_count
FROM general_likes_artists gla
JOIN artists ON artists.id = gla.artist_id
LEFT JOIN LATERAL (
SELECT id FROM albums
WHERE artist_id = artists.id AND cover_art_path IS NOT NULL
ORDER BY created_at DESC LIMIT 1
) cov ON true
LEFT JOIN LATERAL (
SELECT count(*) AS album_count
FROM albums WHERE artist_id = artists.id
) cnt ON true
WHERE gla.user_id = $1
ORDER BY random()
LIMIT $2;