fix(playlists): a missing track never seeds For You or Songs-like (#2701)
release / govulncheck (push) Successful in 14s
release / web (push) Successful in 1m11s
release / go (push) Successful in 1m29s
release / integration (push) Successful in 4m27s
release / android (push) Successful in 5m2s
release / Build signed APK (releases and dev) (push) Successful in 5m17s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 1m15s
release / Verify release artifacts (tag releases only) (push) Skipped

PickTopPlayedTracksForUser's liked tier read general_likes without
joining tracks. With no plays to seed from, For You could pick a liked
track whose file is gone. The play tiers were already safe: their
play_events join filters missing_since.

The same gap was in PickTopPlayedTrackForArtistByUser's fallback, which
seeds Songs-like from the artist's newest album when there are no recent
plays. It could pick a missing track, and since #5296 a missing track is
never fetched for similarity, so that seed has no edges either. The
caller already skips an empty seed, so an artist whose tracks are all
missing gets no Songs-like mix instead of one aimed at nothing.

Integration tests cover both cases: a liked-but-missing track is not a
seed, and the Songs-like fallback moves to the next album once the
newest one's track goes missing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 23:10:17 -04:00
co-authored by Claude Opus 5.5
parent 743b6f5eac
commit efa3bf54ce
3 changed files with 97 additions and 0 deletions
+6
View File
@@ -161,9 +161,14 @@ alltime AS (
AND pe.was_skipped = false
GROUP BY t.id
),
-- A likes-only read still joins tracks: a like outlives its file, and a
-- seed whose file is gone points For You at something the user can't hear
-- (#2701). The other two tiers get the same filter from their play_events
-- join.
liked AS (
SELECT gl.track_id AS id, 0::bigint AS c, 2 AS tier
FROM general_likes gl
JOIN tracks t ON t.id = gl.track_id AND t.missing_since IS NULL
WHERE gl.user_id = $1
),
chosen AS (
@@ -201,6 +206,7 @@ SELECT COALESCE(
FROM tracks t
JOIN albums a ON a.id = t.album_id
WHERE t.artist_id = $2
AND t.missing_since IS NULL -- #2701: the play branch filters; this one must too
ORDER BY a.release_date DESC NULLS LAST,
t.disc_number NULLS LAST,
t.track_number NULLS LAST,