While a request downloads, Silo shows "Processing" and nothing else. The Sonarr/Radarr request plugin already reads each request's download queue, but it keeps only a queued or downloading state, and the reconcile pass that asks for it runs every 5 minutes. A requester can't tell whether a title is 5% done, 95% done or stuck. Admins see a raw status string such as downloading/downloading in the queue dialog. Seerr shows a progress bar and an ETA from the same queue data.
Proposal
Have the request-router plugin report download progress, store it on each request target, and show it on the Requests page, the title page, the admin queue, and in the Apple and Android apps.
-
Plugin contract. TargetStatus gains an optional progress: phase, bytes total and left, estimated completion, and the number of downloads. A manifest flag, request_router.reports_download_progress, says the plugin fills it.
-
Polling. A new 1-minute task refreshes targets in downloading, for plugins that set the flag. It applies status changes and progress only. Submission, library checks and notifications stay on the 5-minute reconcile pass. Both tasks take the same advisory lock, so they never run at once. Targets in queued stay on the 5-minute pass because an unreleased movie can sit queued for months.
-
Storage. Nullable download_* columns on media_request_targets. Writing progress leaves the target's updated_at, the request's status and its history alone. The columns clear when a target completes or fails.
-
API v2 (additive). A RequestDownload object with phase, percent, bytes_total, bytes_left, estimated_completion_at, downloads and updated_at. It appears in three places:
RequestTarget.download
MediaRequest.download, which combines all live targets
RequestMediaState.download, on the title detail only
Capability: download_progress_supported on GET /api/v2/requests/status. /api/v1 doesn't change.
-
Phases. queued, downloading, paused, stalled, importing and import_blocked; clients must accept new values. When downloads disagree, the phase that needs attention wins, in this order: import_blocked, stalled, downloading, importing, paused, queued.
-
Web. A progress bar with "Downloading · 43% · about 12 min left", or the phase, on request cards, the title page's request bar, admin queue rows and per-target rows. Request queries refetch every 30 seconds while something is downloading.
No release names, indexers, download clients or file paths reach any client.
Work
Compatibility
Plugins without the flag keep today's behavior and polling cadence. A server that predates this ignores the new plugin field and manifest key. Clients show nothing new until the server reports download_progress_supported.
Out of scope
- Per-episode progress rows. The library's per-season episode counts already show what has arrived.
- Changing when a request counts as available.
- A realtime push channel for requests.
Related issue: #1201. This builds on the request revamp in #1632.
Validation tasks: reaches #1202 C3, #1203 C1, #1204 C2, Silo-Server/silo-apple#328 C2, Silo-Server/silo-apple#329 C2, Silo-Server/silo-android#338 C2 and Silo-Server/silo-android#339 C2 (none run yet). Availability, the request lifecycle and notifications don't change.
AI disclosure
- Harness: T3 Code (Claude Code agent harness)
- Tool(s): Claude Code, GitHub CLI
- Model(s): claude-opus-5-5
- Involvement: AI-assisted; filed at the maintainer's request
- Adversarial review: n/a
While a request downloads, Silo shows "Processing" and nothing else. The Sonarr/Radarr request plugin already reads each request's download queue, but it keeps only a queued or downloading state, and the reconcile pass that asks for it runs every 5 minutes. A requester can't tell whether a title is 5% done, 95% done or stuck. Admins see a raw status string such as
downloading/downloadingin the queue dialog. Seerr shows a progress bar and an ETA from the same queue data.Proposal
Have the request-router plugin report download progress, store it on each request target, and show it on the Requests page, the title page, the admin queue, and in the Apple and Android apps.
Plugin contract.
TargetStatusgains an optionalprogress: phase, bytes total and left, estimated completion, and the number of downloads. A manifest flag,request_router.reports_download_progress, says the plugin fills it.Polling. A new 1-minute task refreshes targets in
downloading, for plugins that set the flag. It applies status changes and progress only. Submission, library checks and notifications stay on the 5-minute reconcile pass. Both tasks take the same advisory lock, so they never run at once. Targets inqueuedstay on the 5-minute pass because an unreleased movie can sit queued for months.Storage. Nullable
download_*columns onmedia_request_targets. Writing progress leaves the target'supdated_at, the request's status and its history alone. The columns clear when a target completes or fails.API v2 (additive). A
RequestDownloadobject withphase,percent,bytes_total,bytes_left,estimated_completion_at,downloadsandupdated_at. It appears in three places:RequestTarget.downloadMediaRequest.download, which combines all live targetsRequestMediaState.download, on the title detail onlyCapability:
download_progress_supportedonGET /api/v2/requests/status./api/v1doesn't change.Phases.
queued,downloading,paused,stalled,importingandimport_blocked; clients must accept new values. When downloads disagree, the phase that needs attention wins, in this order:import_blocked,stalled,downloading,importing,paused,queued.Web. A progress bar with "Downloading · 43% · about 12 min left", or the phase, on request cards, the title page's request bar, admin queue rows and per-target rows. Request queries refetch every 30 seconds while something is downloading.
No release names, indexers, download clients or file paths reach any client.
Work
docs/architecture/media-requests.md(PR feat(requests): show download progress while a request downloads #1649)Compatibility
Plugins without the flag keep today's behavior and polling cadence. A server that predates this ignores the new plugin field and manifest key. Clients show nothing new until the server reports
download_progress_supported.Out of scope
Related issue: #1201. This builds on the request revamp in #1632.
Validation tasks: reaches #1202 C3, #1203 C1, #1204 C2, Silo-Server/silo-apple#328 C2, Silo-Server/silo-apple#329 C2, Silo-Server/silo-android#338 C2 and Silo-Server/silo-android#339 C2 (none run yet). Availability, the request lifecycle and notifications don't change.
AI disclosure