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

+9
View File
@@ -14,6 +14,7 @@ import (
"music-server/internal/config"
"music-server/internal/db/repository"
"music-server/internal/logging"
"music-server/internal/server/middleware"
"music-server/internal/testutil/fakedb"
"github.com/stretchr/testify/require"
@@ -48,6 +49,8 @@ type testEnv struct {
db *fakeDatabase
server *Server
handler http.Handler
// queueID is sent as X-Queue-Id and updated from responses, like a client keeping its queue.
queueID string
}
func writeFile(t *testing.T, path, content string) {
@@ -111,10 +114,16 @@ func (e *testEnv) doBody(method, path, body string, headers ...string) *httptest
if body != "" {
req.Header.Set("Content-Type", "application/json")
}
if e.queueID != "" {
req.Header.Set(middleware.QueueHeader, e.queueID)
}
for i := 0; i+1 < len(headers); i += 2 {
req.Header.Set(headers[i], headers[i+1])
}
rec := httptest.NewRecorder()
e.handler.ServeHTTP(rec, req)
if id := rec.Header().Get(middleware.QueueHeader); id != "" {
e.queueID = id
}
return rec
}