feat(server/playlists): manual Discover refresh endpoint
POST /api/playlists/system/discover/refresh re-runs the system playlist build synchronously for the calling user, then returns their newly-built Discover playlist's UUID and track count. Used by the frontend's "Refresh" affordances (next task) on the Discover detail page header and the home Playlists row tile kebab. Operator's escape hatch when they want a different randomness without waiting for tomorrow's cron tick (e.g., after pasting a Last.fm key, after the daily cover-art enrichment expanded their playable library, or just for the heck of it). Authenticated user only; the authed sub-router's RequireUser middleware handles 401. Each user refreshes only their own Discover — no admin route, no cross-user impersonation. Adds GetSystemPlaylistByVariantForUser sqlc query for the response lookup. Returns playlist_id=null and track_count=0 if the build succeeded but the user's library yielded no eligible tracks (degenerate empty-library).
This commit is contained in:
@@ -119,6 +119,55 @@ func (q *Queries) FinishSystemPlaylistRun(ctx context.Context, arg FinishSystemP
|
||||
return err
|
||||
}
|
||||
|
||||
const getSystemPlaylistByVariantForUser = `-- name: GetSystemPlaylistByVariantForUser :one
|
||||
SELECT p.id, p.user_id, p.name, p.kind, p.system_variant,
|
||||
p.seed_artist_id, p.cover_path, p.track_count
|
||||
FROM playlists p
|
||||
WHERE p.user_id = $1
|
||||
AND p.kind = 'system'
|
||||
AND p.system_variant = $2
|
||||
ORDER BY p.created_at DESC
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetSystemPlaylistByVariantForUserParams struct {
|
||||
UserID pgtype.UUID
|
||||
SystemVariant *string
|
||||
}
|
||||
|
||||
type GetSystemPlaylistByVariantForUserRow struct {
|
||||
ID pgtype.UUID
|
||||
UserID pgtype.UUID
|
||||
Name string
|
||||
Kind string
|
||||
SystemVariant *string
|
||||
SeedArtistID pgtype.UUID
|
||||
CoverPath *string
|
||||
TrackCount int32
|
||||
}
|
||||
|
||||
// Returns the user's system playlist for the given variant
|
||||
// ('for_you' / 'songs_like_artist' / 'discover'), or pgx.ErrNoRows
|
||||
// when the user hasn't built that variant yet. For
|
||||
// 'songs_like_artist' (which can have multiple rows per user, one
|
||||
// per seed), this returns whichever LIMIT 1 picks — callers that
|
||||
// need all instances should use a different query.
|
||||
func (q *Queries) GetSystemPlaylistByVariantForUser(ctx context.Context, arg GetSystemPlaylistByVariantForUserParams) (GetSystemPlaylistByVariantForUserRow, error) {
|
||||
row := q.db.QueryRow(ctx, getSystemPlaylistByVariantForUser, arg.UserID, arg.SystemVariant)
|
||||
var i GetSystemPlaylistByVariantForUserRow
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.Name,
|
||||
&i.Kind,
|
||||
&i.SystemVariant,
|
||||
&i.SeedArtistID,
|
||||
&i.CoverPath,
|
||||
&i.TrackCount,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getSystemPlaylistRun = `-- name: GetSystemPlaylistRun :one
|
||||
SELECT user_id, last_run_at, last_run_date, in_flight, last_error
|
||||
FROM system_playlist_runs
|
||||
|
||||
@@ -154,3 +154,19 @@ INSERT INTO playlists (
|
||||
kind, system_variant, seed_artist_id, cover_path
|
||||
) VALUES ($1, $2, '', false, 'system', $3, $4, $5)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetSystemPlaylistByVariantForUser :one
|
||||
-- Returns the user's system playlist for the given variant
|
||||
-- ('for_you' / 'songs_like_artist' / 'discover'), or pgx.ErrNoRows
|
||||
-- when the user hasn't built that variant yet. For
|
||||
-- 'songs_like_artist' (which can have multiple rows per user, one
|
||||
-- per seed), this returns whichever LIMIT 1 picks — callers that
|
||||
-- need all instances should use a different query.
|
||||
SELECT p.id, p.user_id, p.name, p.kind, p.system_variant,
|
||||
p.seed_artist_id, p.cover_path, p.track_count
|
||||
FROM playlists p
|
||||
WHERE p.user_id = $1
|
||||
AND p.kind = 'system'
|
||||
AND p.system_variant = $2
|
||||
ORDER BY p.created_at DESC
|
||||
LIMIT 1;
|
||||
|
||||
Reference in New Issue
Block a user