v2026.06.06 — UPnP recovery, library watcher, artist discovery, request auto-poll #87

Merged
bvandeusen merged 18 commits from dev into main 2026-06-06 23:31:28 -04:00
Owner

Batch of four features, all CI-green on dev head (8f29cc74). Cross-platform features (#371, #369) landed on server + web + native together.

UPnP / Sonos — graceful recovery (Android)

  • Idle-revert: after 5 minutes paused on a UPnP/Sonos route, the output reverts to the phone speaker — so a stale Sonos selection can't make a later "tap play" silently do nothing.
  • Play-intent recovery: a play() that fails its SOAP (dead/stale renderer) now reverts to phone and honors the tap (resumes locally) instead of swallowing it.
  • Fail-fast: transport SOAP gets a 2 s connect timeout (vs the shared 10 s) so the revert feels instant rather than a long stall.

Library — filesystem watcher + scheduler retirement (server, web)

  • fsnotify watcher: new/changed files are picked up within seconds (debounced, recursive), scanning just the affected paths and enriching their cover art inline (local instant, remote rate-limited) — "drop a file → it appears with art in seconds."
  • Scheduler retired: the configurable scan scheduler (scan_schedule table, GET/PATCH endpoints, web admin card) is removed in favor of the watcher + startup delta walk + a fixed 12 h safety-net walk. Migration 0033 drops the table.

Artist detail — discovery (server, web, native)

  • Similar artists strip (in-library, ranked by similarity score) and per-user top tracks panel on the artist page, on both clients. New /api/artists/{id}/similar + /top-tracks endpoints.

Requests — live progress auto-poll (web, native)

  • Native RequestsViewModel now polls while a request is mid-ingest (silent reloads, paused when nothing's in-flight) for parity with the web auto-poll, and the SSE-driven refresh updates in place instead of flashing a spinner. Web discover submit invalidates the requests query so a new request shows immediately. (The notifications-inbox half was deferred.)

🤖 Generated with Claude Code

Batch of four features, all CI-green on `dev` head (`8f29cc74`). Cross-platform features (#371, #369) landed on server + web + native together. ## UPnP / Sonos — graceful recovery (Android) - **Idle-revert:** after 5 minutes paused on a UPnP/Sonos route, the output reverts to the phone speaker — so a stale Sonos selection can't make a later "tap play" silently do nothing. - **Play-intent recovery:** a `play()` that fails its SOAP (dead/stale renderer) now reverts to phone **and** honors the tap (resumes locally) instead of swallowing it. - **Fail-fast:** transport SOAP gets a 2 s connect timeout (vs the shared 10 s) so the revert feels instant rather than a long stall. ## Library — filesystem watcher + scheduler retirement (server, web) - **fsnotify watcher:** new/changed files are picked up within seconds (debounced, recursive), scanning just the affected paths and enriching their cover art inline (local instant, remote rate-limited) — "drop a file → it appears with art in seconds." - **Scheduler retired:** the configurable scan scheduler (`scan_schedule` table, GET/PATCH endpoints, web admin card) is removed in favor of the watcher + startup delta walk + a fixed 12 h safety-net walk. Migration 0033 drops the table. ## Artist detail — discovery (server, web, native) - **Similar artists** strip (in-library, ranked by similarity score) and **per-user top tracks** panel on the artist page, on both clients. New `/api/artists/{id}/similar` + `/top-tracks` endpoints. ## Requests — live progress auto-poll (web, native) - Native `RequestsViewModel` now polls while a request is mid-ingest (silent reloads, paused when nothing's in-flight) for parity with the web auto-poll, and the SSE-driven refresh updates in place instead of flashing a spinner. Web discover submit invalidates the requests query so a new request shows immediately. (The notifications-inbox half was deferred.) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bvandeusen added 18 commits 2026-06-06 23:31:17 -04:00
perf(android): fail-fast connect timeout for UPnP transport SOAP
android / Build + lint + test (push) Failing after 1m8s
6b11208e5a
Add Scanner.ScanFiles (watcher-driven targeted scan returning changed album
IDs) and a recursive fsnotify Watcher that debounces filesystem events and
enriches just the affected albums inline. Pure classifyEvent/drainPending
seams unit-tested; ScanFiles covered in the scanner integration test.
Wire the fsnotify watcher and a fixed 12h safety-net delta walk in main;
remove the configurable scan scheduler (scheduler.go, scan_schedule table via
migration 0033, GET/PATCH /api/admin/scan/schedule, and the server/api
plumbing). Manual scan + scan status are unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
style(server): gofmt watcher_test map alignment
test-go / test (push) Failing after 10s
test-web / test (push) Successful in 33s
test-go / integration (push) Failing after 4m27s
e95138d412
test(server): drop removed scheduler arg from New() callers
test-go / test (push) Successful in 28s
test-go / integration (push) Successful in 4m27s
a766b7193f
GET /api/artists/{id}/similar — in-library artists ranked by similarity
score (deduped across sources), ArtistRef list with cover + album count.
GET /api/artists/{id}/top-tracks — current user's most-played tracks for
the artist (skips excluded, quarantine filtered).
feat(android): similar-artists strip + top-tracks on artist detail
test-go / test (push) Successful in 32s
test-web / test (push) Successful in 40s
android / Build + lint + test (push) Failing after 1m16s
test-go / integration (push) Successful in 4m29s
12a8cfccb5
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(android): extract ArtistSuccessBody to satisfy detekt LongMethod
android / Build + lint + test (push) Failing after 2m56s
483804fc9e
fix(android): grid items() resolution on artist detail (drop bad alias)
android / Build + lint + test (push) Successful in 3m35s
c8b21aa76e
feat: poll in-flight requests on native + refresh after submit (#369)
test-web / test (push) Successful in 33s
android / Build + lint + test (push) Successful in 3m37s
8f29cc7414
Native RequestsViewModel gains poll-while-approved (silent reloads, paused
when nothing in-flight) for parity with the web auto-poll, and the SSE
collector now reloads silently instead of flashing the loading spinner.
Web discover submit invalidates qk.myRequests() so a new request appears
on /requests immediately.
bvandeusen merged commit 7c791dc8e4 into main 2026-06-06 23:31:28 -04:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bvandeusen/minstrel#87