Store each client's play queue in the database

The queue lived in memory and was shared by all clients, so a restart or a
finished sync cleared it. Every client now has its own queue in the new
queue and queue_song tables (added to the undeployed migration 000006).

The music endpoints return the queue ID in the X-Queue-Id header and expect
it back. A request without an ID, or with an ended one, starts a new queue.
/music/reset ends the queue and returns a new ID, and a sync ends all
running queues. Ended queues are kept as history.

The deprecated legacy routes without the /api/v1 prefix are removed.
This commit is contained in:
Sansan committed 2026-10-07 20:03:03 +02:00
1 parent b5dc42b654
commit a705d7b476
28 files changed
+1103 -320

No files matched your search

+3 -4
View File
@@ -55,7 +55,6 @@ func TestLibraryEndpointErrors(t *testing.T) {
func TestLibraryEndpointsRequireToken(t *testing.T) {
e := newTestEnv(t, withAuth("secret"))
assert.Equal(t, http.StatusUnauthorized, e.do(http.MethodGet, "/api/v1/soundtracks").Code)
assert.Equal(t, http.StatusNotFound, e.do(http.MethodGet, "/soundtracks").Code, "not available on legacy routes")
}
func TestSongFileLockedDuringSync(t *testing.T) {
@@ -72,11 +71,11 @@ func TestSongFileLockedDuringSync(t *testing.T) {
func TestQueueResponsesIncludeUUIDs(t *testing.T) {
e := newTestEnv(t)
song := e.addSong("Game A", "Song", "x")
require.Equal(t, http.StatusOK, e.do(http.MethodGet, "/music/rand").Code)
require.Equal(t, http.StatusOK, e.do(http.MethodGet, "/music/addQue").Code)
require.Equal(t, http.StatusOK, e.do(http.MethodGet, "/api/v1/music/rand").Code)
require.Equal(t, http.StatusOK, e.do(http.MethodGet, "/api/v1/music/addQue").Code)
var info map[string]any
require.NoError(t, json.Unmarshal(e.do(http.MethodGet, "/music/info").Body.Bytes(), &info))
require.NoError(t, json.Unmarshal(e.do(http.MethodGet, "/api/v1/music/info").Body.Bytes(), &info))
assert.Equal(t, song.Uuid.String(), info["SongUuid"])
assert.Equal(t, song.SoundtrackUuid.String(), info["SoundtrackUuid"])