feat(library): add cancel, status, and recovery for Aurral album downloads - #918
Conversation
…arts Album jobs flagged for cancellation ignore late pipeline transitions and restart moves interrupted cancellations to cancelled instead of pending.
Adds POST /api/library/albums/aurral/:canonicalId/cancel. Pending tracks are cancelled immediately, active transfers are stopped through the existing provider cleanup, and finished tracks stay in place.
Adds GET /api/library/albums/aurral/:canonicalId/status and aurral:<id> keys on the batch download status route. Status combines canonical track availability with per-track jobs and includes an actionable recovery for blocked and failed albums. Album add and request responses include the same albumStatus.
…source Re-requesting an album requeues its cancelled and failed tracks in place. Without a configured download source the request keeps the album state, queues nothing, and reports the missing source instead of creating jobs that can only fail.
Activity history records cancelled album track downloads as cancelled instead of timing them out as failures, and the library and activity views render the new state. Documents the Aurral album status and cancel routes.
Aurral album requests were recorded as Lidarr searches and the sync looked up their canonical album ID in Lidarr, which marked cancelled or queued Aurral albums as not found.
Aurral preview image readyThis image was rebuilt from the latest push to this pull request. It will be replaced when you push another change. docker pull ghcr.io/lklynet/aurral:pr-918To test it with your existing Docker Compose setup:
|
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Important Review skippedReview was skipped as selected files did not have any reviewable changes. ⚙️ Run configurationConfiguration used: Repository UI Review profile: QUIET Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThe change adds cancellation states and recovery handling for download jobs, Aurral album status summaries and cancellation operations, and retry behavior for cancelled or failed tracks. New album endpoints and prefixed download-status lookups expose Aurral status. History records manager ownership and cancellation, while the frontend displays cancelled requests. Priority: ➖ Normal Merge Risk: 🔵 Low · up to Cancellation activity can show a misleading state, and an album with same-title tracks may miss a download. These bounded cases warrant fixes or explicit acceptance before merge. Security Architecture ReviewSecurity architecture risk: 🟡 Moderate · up to Cancellation has appropriate permission checks, but a retry can race with cleanup and a restart can leave cancelled work appearing queued. These are bounded lifecycle risks rather than evidence of unauthorized access. Retained concerns
Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 11 files. (1 skipped: 1 unsupported.) Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Note
Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.
🟡 Other comments (2)
backend/services/aurralHistoryService.js-609-613 (1)
609-613: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winRepresent
cancel_requestedjobs as cancellation-pending.When provider cleanup fails, the tracker remains
cancel_requested. The history sync skips this state, so the row remainsprocessingwithout showing that cancellation is pending. Do not mark the rowcancelledonly because it is stale. Provider work may still be active. Record a cancellation-pending state and usecancelledonly after cleanup succeeds and the tracker reachescancelled.backend/services/aurralAlbumJobs.js-13-26 (1)
13-26: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUse title fallback only when both MBIDs are absent.
jobMatchesTrackfalls back to the normalized title when only one side has an MBID. An album can contain distinct canonical tracks with the same title because tracks use separate canonical IDs, while imported tracks can have a null MBID. During_finishAurralAlbum, this can match one track to another track’s active or completed job and skip its download.Suggested fix
export function jobMatchesTrack(job, track) { - if (job.trackMbid && track.mbid) { - return normalizeKey(job.trackMbid) === normalizeKey(track.mbid); + const jobMbid = normalizeKey(job.trackMbid); + const trackMbid = normalizeKey(track.mbid); + if (jobMbid || trackMbid) { + return Boolean(jobMbid && trackMbid) && jobMbid === trackMbid; } return normalizeKey(job.trackName) === normalizeKey(track.title); }
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: QUIET
Plan: Advanced
Run ID: 41fc2af2-53f4-4afd-9c82-ada282a6c0d7
📒 Files selected for processing (12)
.tests/history/aurral-history.test.js.tests/library/aurral-album-lifecycle.test.js.tests/library/aurral-owned-writes.test.jsbackend/routes/library/handlers/albums.jsbackend/routes/library/handlers/downloads.jsbackend/services/aurralAlbumJobs.jsbackend/services/aurralHistoryService.jsbackend/services/libraryManager.jsbackend/services/weeklyFlow/weeklyFlowDownloadTracker.jsdocs/src/content/docs/api/endpoints.mdxfrontend/src/pages/LibraryPage.jsxfrontend/src/pages/activity/ActivityRequestRow.jsx
Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.
Available on nightlyA linked pull request was merged into docker pull ghcr.io/lklynet/aurral:nightly
|
> Stacked on #918. This PR targets that branch, so the diff shows only the monitoring changes. After #918 merges, rebase onto `main` and retarget before merging. ## What changed - Aurral-managed artists can be monitored without Lidarr. `PUT /api/library/artists/:mbid` and artist add accept these `monitorOption` values: - `all` and `missing` queue every album that is not complete yet. - `latest` and `first` queue the newest or oldest album. - `future` queues only albums released after monitoring starts. - `none` stops new work and keeps existing media. `existing` applies only to Lidarr and returns `400 unsupported_monitor_mode` for Aurral artists. - Only official albums and EPs with no secondary type are picked up. Albums managed by Lidarr are skipped and listed in `monitoring.skipped`. The chosen albums go through the existing Aurral album request and download pipeline, in a system task. - If artist metadata can't be loaded, the request returns `503 metadata_unavailable` and the previous monitor mode is kept. - `PUT /api/library/albums/aurral/:canonicalId` with `{ "monitored": false }` cancels that album's downloads and keeps finished tracks. The choice is kept when the artist's monitoring changes. `{ "monitored": true }` queues the album again. - A daily `aurral-monitoring-reconcile` system task queues newly listed releases for monitored Aurral artists. It doesn't requeue albums already in the library, and one artist's metadata failure doesn't stop the run. - The library-ownership cache now picks up changes made by other processes. Before this change, albums created by the system task looked unmanaged in the web process until a restart. - The user and API docs cover Aurral monitoring. ## Why Monitoring and new-release acquisition required Lidarr. This lets users who don't run Lidarr monitor artists and get their albums through Aurral's own download sources. Artists and albums managed by Lidarr keep their current behavior, and Aurral monitoring never calls Lidarr. This is part of the optional-Lidarr roadmap. ## Scope checklist - [x] This pull request has one clear purpose - [x] I kept unrelated fixes, refactors, formatting changes, dependency updates, and features out of this pull request - [x] If this adds a feature, I linked the approved feature request or included the Discord context in the Why section ## Linked issue No linked issue. The work is tracked on the maintainer roadmap for optional Lidarr support. ## Testing - `npm run lint`: passed - `npm test`: 1,354 passed, 0 failed - `npm run docs:build`: passed - New `.tests/library/aurral-monitoring.test.js` goes through the artist and album routes and the system task, using a local metadata stub. It asserts that Lidarr is never called, and covers: - release eligibility and each monitor mode - a metadata outage - skipping Lidarr-managed albums - album overrides - repeated reconciliation, and one artist failing during reconciliation - `.tests/library/library-management.test.js` adds a check that writes through a second SQLite connection. The round-trip assertion now ignores the new `updatedAt` field and checks it separately. - Each new test failed before its change. - Live check against the shared test services: - Added an artist with `latest`: the background system task created the album and queued its 7 tracks. - Reconciliation ran three times without creating duplicates. - The live check caught the ownership cache bug above. After the fix, the running web process cancelled an album created by the background task without a restart. - Setting `none` stopped new work. - No test files were left in the shared download folders. ## Release impact - [ ] Major: incompatible change - [x] Minor: backward-compatible feature - [ ] Patch: backward-compatible fix - [ ] None: documentation, CI, tests, or internal-only change
What changed
POST /api/library/albums/aurral/:canonicalId/cancel. Queued tracks stop right away, and active transfers are stopped through each download source's existing cleanup. Finished tracks stay in place.GET /api/library/albums/aurral/:canonicalId/statusreports one status for the album:complete,downloading,queued,blocked,cancelled,failed,partial, ormissing. The response has per-track counts, and arecoveryobject when the user needs to do something (download_source_missing,review_required,source_failed).GET /api/library/downloads/statusacceptsaurral:<canonicalId>keys. Album add and request responses include the same status asalbumStatus.Why
Aurral albums (from #855) queue one download job per track, but they had no way to cancel, no album-level status, and restarts and late errors could bring back or fail work the user had stopped. Aurral albums need a full download lifecycle before Aurral can manage albums without Lidarr. Lidarr behavior is unchanged. None of these paths call Lidarr.
This is part of the optional-Lidarr roadmap. Artist monitoring builds on it in the stacked follow-up PR.
Scope checklist
Linked issue
No linked issue. The work is tracked on the maintainer roadmap for optional Lidarr support.
UI changes
No new screens or controls. The library album view and Activity now show a
cancelledtrack state (an X icon labelled "Cancelled") instead of treating it as searching or failed. I didn't capture screenshots because no UI control can cancel an album yet. The destination and cancel controls come in a later PR.Testing
npm run lint: passednpm test: 1,347 passed, 0 failednpm run docs:build: passed.tests/library/aurral-album-lifecycle.test.jscovers:.tests/library/aurral-owned-writes.test.jsand.tests/history/aurral-history.test.js.managedBy: "aurral":Release impact