feat(#392): lidarr reconciler publishes request.status_changed on complete
Slice 3b — extends event publishing to background workers. When the reconciler matches an approved Lidarr request against the library and flips it to 'completed', it now publishes a request.status_changed event scoped to the original requester so their /requests page invalidates without polling. Three call sites — one per kind (artist / album / track) — capture the completed row instead of discarding it so the publish has the user_id. Bus plumbing: the reconciler runs in cmd/minstrel/main.go which constructs services before server.New is called. Moved bus construction into main; the Server struct gained a Bus field that Router() reads, falling back to a fresh local instance when nil (test contexts). Result: one bus per process shared by every publisher and the SSE subscriber endpoint. reconciler.go inlines a uuid->string helper rather than reaching into internal/api for one — avoids a back-edge dependency. Test compat: 9 NewReconciler call sites in reconciler_integration_test.go get `nil` for the new bus param. The reconciler's publishCompleted helper is a no-op when the bus is nil so tests that don't care about events keep passing. Scanner producer (scan.progress) deferred to slice 3c — needs more thought about which lifecycle transitions warrant events vs. flood the stream. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/config"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/coverart"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/db"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/eventbus"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/library"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/lidarrconfig"
|
||||
"git.fabledsword.com/bvandeusen/minstrel/internal/lidarrrequests"
|
||||
@@ -146,7 +147,12 @@ func run() error {
|
||||
// import requests and reconciles them against the library. Short-circuits
|
||||
// to no-op when lidarr_config.enabled = false.
|
||||
lidarrCfg := lidarrconfig.New(pool)
|
||||
lidarrReconciler := lidarrrequests.NewReconciler(pool, lidarrCfg, logger.With("component", "lidarr"))
|
||||
// Live-event bus shared between SSE subscribers (api.Mount) and
|
||||
// background workers that publish (reconciler today; scanner later).
|
||||
// Constructed before any service that publishes so they all share the
|
||||
// same instance.
|
||||
bus := eventbus.New()
|
||||
lidarrReconciler := lidarrrequests.NewReconciler(pool, lidarrCfg, logger.With("component", "lidarr"), bus)
|
||||
go lidarrReconciler.Run(ctx)
|
||||
|
||||
// Ensure DataDir exists before any service tries to write into it.
|
||||
@@ -173,6 +179,7 @@ func run() error {
|
||||
srv := server.New(logger, pool, scanner, subsonic.Config{
|
||||
AllowPlaintextPassword: cfg.Subsonic.AllowPlaintextPassword,
|
||||
}, cfg.Events, cfg.Recommendation, cfg.Storage.DataDir, cfg.Branding, coverEnricher, cfg.Library.CoverArtBackfillCap, coverSettings, scanner, scanCfg, scheduler)
|
||||
srv.Bus = bus
|
||||
playlists.StartSystemPlaylistCron(ctx, pool, logger.With("component", "system_playlist_cron"), cfg.Storage.DataDir)
|
||||
httpServer := &http.Server{
|
||||
Addr: cfg.Server.Address,
|
||||
|
||||
Reference in New Issue
Block a user