feat(web/player): self-heal a stale system-playlist / radio queue on total failure
test-web / test (push) Successful in 39s
test-web / test (push) Successful in 39s
When the whole queue proves unplayable (e.g. a tab left open across the daily system-playlist rebuild — the exact stale-snapshot case), the player now re-pulls the fresh snapshot and resumes instead of dead-ending on "Try again". The seeder hands the store an opaque refetch closure so the store stays decoupled from the playlist API and the per-artist (songs_like_artist) identity problem: single-instance variants re-pull via systemShuffle, per-artist mixes via getPlaylist(id), radio re-seeds from its track. Bounded to one self-heal per exhaustion (reset on the next successful play) so a still-broken refresh can't loop; "Try again" stays the genuine last resort. Wired from PlaylistCard, the playlist detail page, and playRadio. Issue #968. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import type { TrackRef, PlaylistDetail } from '$lib/api/types';
|
||||
import { systemShuffle, getPlaylist } from '$lib/api/playlists';
|
||||
import { playlistTrackToRef } from './playlistTrackToRef';
|
||||
|
||||
// #968: builds the self-heal closure for a system-playlist queue. On total
|
||||
// playback failure (every queued track unplayable — typically a stale tab
|
||||
// left open across the daily rebuild) the player calls this to re-pull the
|
||||
// current snapshot and resume.
|
||||
//
|
||||
// Single-instance variants (for_you, discover, deep_cuts, …) re-pull by
|
||||
// variant via the rotation-aware shuffle endpoint. Per-artist mixes
|
||||
// (songs_like_artist — one playlist per seed artist) can't be addressed by
|
||||
// variant alone, so they re-pull by playlist id. Mirrors the play routing
|
||||
// in PlaylistCard.
|
||||
|
||||
function toRefs(detail: PlaylistDetail): TrackRef[] {
|
||||
return detail.tracks
|
||||
.map((r) => playlistTrackToRef(r))
|
||||
.filter((t): t is TrackRef => t !== null);
|
||||
}
|
||||
|
||||
export function systemPlaylistRefetch(opts: {
|
||||
variant: string;
|
||||
playlistId: string;
|
||||
perArtist: boolean;
|
||||
}): () => Promise<TrackRef[]> {
|
||||
return async () => {
|
||||
const detail = opts.perArtist
|
||||
? await getPlaylist(opts.playlistId)
|
||||
: await systemShuffle(opts.variant);
|
||||
return toRefs(detail);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user