feat(subsonic): getAlbumList2 recent and frequent read the caller's play history (#6293)
release / govulncheck (push) Successful in 20s
release / web (push) Successful in 1m37s
release / go (push) Successful in 1m45s
release / integration (push) Failing after 5m27s
release / android (push) Successful in 5m40s
release / Build signed APK (releases and dev) (push) Successful in 5m55s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Skipped
release / Verify release artifacts (tag releases only) (push) Skipped

type=recent orders the caller's albums by their latest play (skips
included); type=frequent orders them by completed plays (skips
excluded). Plays of tracks whose file is gone do not count, and both
page by size/offset like the other types.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-23 13:58:09 -04:00
co-authored by Claude Opus 5.5
parent 09e78962b2
commit f3b124f9b2
4 changed files with 375 additions and 4 deletions
+50
View File
@@ -99,6 +99,56 @@ WHERE EXISTS (
ORDER BY albums.sort_title, albums.id
LIMIT sqlc.arg(lim) OFFSET sqlc.arg(off);
-- name: ListAlbumsRecentlyPlayedByUser :many
-- The user's albums, most recently played first: an album's time is its
-- latest play of any of its tracks, skips included, since a skip is still
-- the user reaching for that album. Plays of tracks whose file is gone do
-- not count. Serves Subsonic getAlbumList2?type=recent.
--
-- Aggregates play_events per track first (play_events_user_track_idx), then
-- folds tracks into albums, so the join runs over distinct tracks rather
-- than every play.
WITH plays AS (
SELECT track_id, max(started_at) AS last_played
FROM play_events
WHERE user_id = sqlc.arg(user_id)
GROUP BY track_id
), per_album AS (
SELECT t.album_id, max(p.last_played) AS last_played
FROM plays p
JOIN tracks t ON t.id = p.track_id
WHERE t.missing_since IS NULL
GROUP BY t.album_id
)
SELECT albums.*
FROM per_album pa
JOIN albums ON albums.id = pa.album_id
ORDER BY pa.last_played DESC, albums.id
LIMIT sqlc.arg(lim) OFFSET sqlc.arg(off);
-- name: ListAlbumsFrequentlyPlayedByUser :many
-- The user's albums, most played first: an album's count is the user's
-- completed plays across its tracks. Skips do not count, so skipping
-- through an album does not make it a favourite. Plays of tracks whose file
-- is gone do not count. Serves Subsonic getAlbumList2?type=frequent.
WITH plays AS (
SELECT track_id, count(*) AS cnt
FROM play_events
WHERE user_id = sqlc.arg(user_id) AND was_skipped = false
GROUP BY track_id
), per_album AS (
SELECT t.album_id, sum(p.cnt) AS cnt
FROM plays p
JOIN tracks t ON t.id = p.track_id
WHERE t.missing_since IS NULL
GROUP BY t.album_id
)
SELECT albums.*
FROM per_album pa
JOIN albums ON albums.id = pa.album_id
ORDER BY pa.cnt DESC, albums.id
LIMIT sqlc.arg(lim) OFFSET sqlc.arg(off);
-- name: SearchAlbums :many
SELECT * FROM albums
WHERE title ILIKE '%' || $1 || '%'