feat(notifications): requests and flags reach the people who act on them (#5340)

- A new request still pending after any auto-approval notifies the
  admins (request_pending), but not the requester if they are an admin.
  A request that dedups into one already in flight is not announced again.
- Approving or rejecting a request notifies the requester, and a
  rejection carries the admin's notes as the reason. An admin deciding
  their own request gets nothing.
- The reconciler notifies the requester when their request arrives
  (request_completed), linking the matched album or artist.
- A request the re-acquisition sweeper files and cannot approve itself
  notifies the admins.
- A quarantine flag notifies every admin except the flagger, naming the
  track, the flagger and the reason.

lidarrrequests.Service.CreateTracked reports whether a request was
inserted or deduped; Create wraps it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 07:17:11 -04:00
co-authored by Claude Opus 5.5
parent 94ef8c1887
commit 069baeb14d
13 changed files with 486 additions and 33 deletions
+10 -2
View File
@@ -314,7 +314,13 @@ func run() error {
}
return lidarr.NewClient(c.BaseURL, c.APIKey)
}
// The notifications inbox's one writer (M489), shared by every
// background producer started here. The API builds its own over the
// same pool and bus.
notifier := notifications.New(pool, bus, logger.With("component", "notifications"))
lidarrReconciler := lidarrrequests.NewReconciler(pool, lidarrCfg, lidarrClientFn, logger.With("component", "lidarr"), bus)
lidarrReconciler.SetNotifier(notifier)
go lidarrReconciler.Run(ctx)
// Missing-file re-acquisition (milestone #290). Turns albums whose files
@@ -332,12 +338,14 @@ func run() error {
if reacqErr != nil {
logger.Warn("reacquisition: using default settings", "err", reacqErr)
}
go reacquisition.NewSweeper(
reacqSweeper := reacquisition.NewSweeper(
pool,
reacqSettings,
lidarrrequests.NewService(pool, lidarrCfg, lidarrClientFn, nil),
logger.With("component", "reacquisition"),
).Run(ctx)
)
reacqSweeper.SetNotifier(notifier)
go reacqSweeper.Run(ctx)
// library_changes compactor (#357 follow-up). Daily tick; deletes
// rows older than the configured retention so the change-log table