feat(subsonic): wire /rest/scrobble into playevents.Writer
submission=false → play_started (replaces in-memory nowPlayingMap). submission=true (default) → synthetic completed play. The nowPlayingMap struct + factory + the nowPlaying field on mediaHandlers are deleted; play_events WHERE ended_at IS NULL is now the source of truth for 'currently playing,' reachable from M3+ work. api.Mount now takes the shared *playevents.Writer instead of cfg so the same writer instance feeds both surfaces.
This commit is contained in:
+4
-11
@@ -6,26 +6,19 @@ package api
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/auth"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/config"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/playevents"
|
||||
)
|
||||
|
||||
// Mount attaches /api/* handlers to r. Public endpoints (login) are outside
|
||||
// RequireUser; everything else is gated by the middleware.
|
||||
func Mount(r chi.Router, pool *pgxpool.Pool, logger *slog.Logger, cfg config.EventsConfig) {
|
||||
w := playevents.NewWriter(
|
||||
pool, logger,
|
||||
time.Duration(cfg.SessionTimeoutMinutes)*time.Minute,
|
||||
cfg.SkipMaxCompletionRatio,
|
||||
cfg.SkipMaxDurationPlayedMs,
|
||||
)
|
||||
h := &handlers{pool: pool, logger: logger, events: w}
|
||||
// RequireUser; everything else is gated by the middleware. The events writer
|
||||
// is shared with the Subsonic mount so /rest/scrobble feeds the same store.
|
||||
func Mount(r chi.Router, pool *pgxpool.Pool, logger *slog.Logger, events *playevents.Writer) {
|
||||
h := &handlers{pool: pool, logger: logger, events: events}
|
||||
|
||||
r.Route("/api", func(api chi.Router) {
|
||||
api.Post("/auth/login", h.handleLogin)
|
||||
|
||||
@@ -2,13 +2,16 @@ package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/config"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/playevents"
|
||||
)
|
||||
|
||||
// newLibraryRouter builds a test-only chi router with the library handlers
|
||||
@@ -435,11 +438,9 @@ func TestHandleListArtists_EmptyDB(t *testing.T) {
|
||||
func TestRoutesRegisteredInMount(t *testing.T) {
|
||||
h, _ := testHandlers(t)
|
||||
r := chi.NewRouter()
|
||||
Mount(r, h.pool, h.logger, config.EventsConfig{
|
||||
SessionTimeoutMinutes: 30,
|
||||
SkipMaxCompletionRatio: 0.5,
|
||||
SkipMaxDurationPlayedMs: 30000,
|
||||
})
|
||||
w := playevents.NewWriter(h.pool, slog.New(slog.NewTextHandler(io.Discard, nil)),
|
||||
30*time.Minute, 0.5, 30000)
|
||||
Mount(r, h.pool, h.logger, w)
|
||||
|
||||
paths := []string{
|
||||
"/api/artists",
|
||||
|
||||
Reference in New Issue
Block a user