Skip to content

Commit 49ba944

Browse files
authored
docs: document the real-time management UI streams (#83)
1 parent db9393d commit 49ba944

5 files changed

Lines changed: 172 additions & 6 deletions

File tree

‎website/guide/getting-started.md‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,32 @@ step 4:
9595
}
9696
```
9797

98+
Worth deciding now: **jack's copy of a download outlives the import.** Radarr
99+
and Sonarr read the finished file out of this folder and write your library
100+
copy, but nothing cleans up jack's — so the folder grows with every grab. Add
101+
`unlinkImportedFiles` to have jack drop its copy once the import is confirmed:
102+
103+
```jsonc
104+
{
105+
"downloads": {
106+
"completedPath": "/data/torrents/completed",
107+
"unlinkImportedFiles": true
108+
}
109+
}
110+
```
111+
112+
It's off by default because it deletes files, and it's a plain `unlink` of that
113+
one file — if your *arr hardlinked into the library, the library keeps the data;
114+
if it copied, you get the space back. You can also flip it later from the
115+
management UI without a restart. See
116+
[After the import](/guide/how-it-works#after-the-import) for the full picture,
117+
and [`unlinkImportedFiles`](/reference/configuration#downloads-unlinkimportedfiles)
118+
for the exact guarantees.
119+
120+
Every other key in this block is an optional tuning knob with a sensible
121+
default — see [`downloads`](/reference/configuration#downloads). All of them are
122+
editable later from the management UI, so you don't have to get them right here.
123+
98124
### `servers`
99125

100126
One entry per Radarr/Sonarr. Set each server's URL, and reference the API keys

‎website/guide/how-it-works.md‎

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Learn how jack connects Radarr and Sonarr through Torznab and qBittorrent-compatible APIs to search and transfer media between trusted peers.
2+
description: Learn how jack connects Radarr and Sonarr through Torznab and qBittorrent-compatible APIs to search, transfer, and import media between trusted peers, and what happens to downloaded files afterwards.
33
---
44

55
# How it works
@@ -64,6 +64,8 @@ sequenceDiagram
6464
ARR->>JACK: GET /api/v2/torrents/info (poll progress)
6565
JACK-->>ARR: completed → content_path = finished file
6666
Note over ARR: scans completed folder, imports into library
67+
JACK->>ARR: poll history — did the import land?
68+
Note over JACK: confirmed → optionally unlink jack's copy
6769
```
6870

6971
1. You grab a release. Your *arr's download client is the **qBittorrent**
@@ -78,6 +80,45 @@ sequenceDiagram
7880
5. *arr polls jack's `/api/v2/torrents/info` for progress; once jack reports
7981
the torrent complete, *arr scans the completed folder and imports the file
8082
into your library, renamed and tracked.
83+
6. jack watches that *arr's history until the import is confirmed, then — if
84+
you've turned it on — removes its own copy from the completed folder. See
85+
[After the import](#after-the-import) below.
86+
87+
### After the import
88+
89+
Importing doesn't consume the file in `completedPath`. Radarr and Sonarr read
90+
it and write your library copy; jack's copy stays where it was, and jack has no
91+
further use for it — a finished download is never re-served to peers or
92+
re-imported.
93+
94+
That leaves you with two on-disk outcomes, and which one you get is decided by
95+
your *arr, not by jack:
96+
97+
- **Your *arr hardlinked** (its default when the completed folder and the
98+
library live on the same filesystem) — the library entry and jack's copy are
99+
two names for the same bytes. Nothing is duplicated, but the completed folder
100+
keeps filling with entries you'll never look at.
101+
- **Your *arr copied or moved** (different filesystems, or hardlinks disabled) —
102+
the library now holds its own bytes, and jack's copy is a genuine second copy
103+
of every file you've ever grabbed. Left alone, `completedPath` grows without
104+
bound.
105+
106+
[`downloads.unlinkImportedFiles`](/reference/configuration#downloads-unlinkimportedfiles)
107+
is the switch for this. Turn it on and jack unlinks its copy as soon as the
108+
import is confirmed: in the hardlink case that just drops the redundant
109+
directory entry and your library is untouched, and in the copy case it frees the
110+
space. It's **off by default**, so an instance you set up and forget will
111+
accumulate.
112+
113+
The unlink is deliberately narrow. It runs only on an import jack has confirmed
114+
— the destination *arr reports the download in its history, or the manual import
115+
jack pushed reports `completed` — so a queued, in-progress, or failed import
116+
keeps its file, and so does a file another download still needs. jack removes
117+
that one file and nothing else; it never touches your library.
118+
119+
Flip it from **Settings → Downloads** in the [management
120+
UI](/guide/management-ui) or set it in `config.jsonc`. It's the one key in the
121+
`downloads` block that applies without a restart.
81122

82123
## 3. Serving — being a peer to others
83124

‎website/guide/management-ui.md‎

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Manage jack servers, peers, API keys, downloads, catalog requests, and logs from the self-hosted web management console.
2+
description: Manage jack servers, peers, API keys, downloads, catalog requests, and logs from the self-hosted web management console, with live updates over Server-Sent Events.
33
---
44

55
# Management UI
@@ -11,11 +11,11 @@ instance without hand-editing `config.jsonc`. With the
1111
operate jack day to day:
1212

1313
- **Overview** — your configured servers and peers, and whether each one
14-
initialized cleanly.
14+
initialized cleanly, with transfer activity updating live.
1515
- **Catalog** — browse everything your peers share, and request titles into
1616
your library.
1717
- **Downloads** — inspect, cancel, retry, and delete in-flight or finished
18-
grabs.
18+
grabs, updating live as they progress.
1919
- **Peers** and **Servers** — add, edit, and remove your friends and your
2020
Radarr/Sonarr connectors.
2121
- **Settings → Downloads** — the whole
@@ -28,6 +28,28 @@ operate jack day to day:
2828
Don't want it? Delete the `jack-ui` service and the backend's
2929
`JACK_MANAGEMENT_KEY` line to run jack headless.
3030

31+
## Settings → Downloads
32+
33+
The whole [`downloads`](/reference/configuration#downloads) block is editable
34+
here, so there's no reason to hand-edit `config.jsonc` for it:
35+
36+
- **Completed folder**, **simultaneous transfers**, and the
37+
**[drop imported files](/reference/configuration#downloads-unlinkimportedfiles)**
38+
switch — the settings you actually choose — sit at the top.
39+
- **Transfer retries** and **import watcher** tuning are collapsed below, each
40+
labelled with how many of its values you've moved off jack's defaults.
41+
42+
Every field's placeholder is jack's default, and **clearing a field means "use
43+
the default"** — jack drops the key from the config file rather than storing a
44+
blank. `completedPath` is the exception: it has no default, so it can't be
45+
cleared. If your config has no `downloads` block at all, the page offers to set
46+
one up.
47+
48+
One **Save** covers the form and only lights up once something changed;
49+
**Revert** discards your edits. `unlinkImportedFiles` takes effect the moment
50+
you save — **every other key here is read at startup, so restart jack** to apply
51+
it.
52+
3153
## Access control
3254

3355
The UI supports two auth modes, depending on where the management key comes
@@ -60,6 +82,39 @@ separate listener the UI never touches.
6082
See [`apps/ui/README.md`](https://github.com/roziscoding/jack/blob/main/apps/ui/README.md)
6183
for the full UI configuration reference.
6284

85+
## Live updates
86+
87+
The UI doesn't poll. Overview, Downloads, and Settings each hold a
88+
[Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)
89+
stream open through the BFF, and jack pushes a fresh snapshot the moment
90+
something changes — a transfer's progress, a connector's state, a peer or server
91+
you just edited. There is no refresh interval to tune and no manual refresh
92+
button.
93+
94+
The streams are plain `GET` endpoints on the management API:
95+
96+
| Stream | What it pushes |
97+
| --- | --- |
98+
| `/overview/stream` | Connector overview + download state |
99+
| `/downloads/stream` | Every persisted download change |
100+
| `/config/stream` | Peer and server config changes |
101+
102+
Each sends its current snapshot immediately on connect, then a full snapshot per
103+
change — no deltas to reassemble — plus a `ping` event every 15 seconds so idle
104+
proxies don't drop the connection. The Logs page tails `/logs/stream`, which
105+
works the same way except each event is a single log line rather than a
106+
snapshot.
107+
108+
The browser reconnects on its own if a stream drops; Overview and Downloads show
109+
a **Live** badge that flips to **Reconnecting…** while it's down.
110+
111+
**Behind a reverse proxy:** SSE needs response buffering **off** and an idle
112+
timeout **longer than 15 seconds** on whatever sits in front of the UI. jack
113+
sends `X-Accel-Buffering: no` (nginx and compatible proxies honour it) and the
114+
BFF forwards that header, but proxies that buffer regardless — or cut idle
115+
connections early — will leave the UI stuck on **Reconnecting…**. See
116+
[Troubleshooting](/guide/troubleshooting#management-ui-stuck-on-reconnecting).
117+
63118
## Management API
64119

65120
The UI's backing API — the **management API** — is a separate listener on its

‎website/guide/troubleshooting.md‎

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Diagnose jack connectivity, Radarr or Sonarr registration, qBittorrent client checks, downloads, imports, permissions, and peer errors.
2+
description: Diagnose jack connectivity, Radarr or Sonarr registration, qBittorrent client checks, downloads, imports, permissions, management UI live updates, and peer errors.
33
---
44

55
# Troubleshooting
@@ -126,6 +126,50 @@ depends_on:
126126
(This needs `healthcheck` blocks on those services — the linuxserver.io images
127127
ship with them.)
128128

129+
## The completed folder keeps growing
130+
131+
Everything imports fine, but `downloads.completedPath` never shrinks — every
132+
title you've ever grabbed is still sitting there.
133+
134+
That's the default behaviour, not a bug. Importing doesn't consume the file:
135+
Radarr/Sonarr read it and write your library copy, and jack's copy stays put.
136+
Whether that costs you real space depends on your *arr — a hardlinked import
137+
shares bytes with the library, a copied one doesn't — but either way the folder
138+
fills up.
139+
140+
**Fix:** turn on
141+
[`downloads.unlinkImportedFiles`](/reference/configuration#downloads-unlinkimportedfiles),
142+
in `config.jsonc` or from **Settings → Downloads** in the management UI. It
143+
applies immediately, with no restart. jack then unlinks its copy as each import
144+
is confirmed — safely: only on a confirmed import, only that one file, never
145+
your library. Details in [After the import](/guide/how-it-works#after-the-import).
146+
147+
This only affects downloads imported **after** you enable it. Files already in
148+
the folder are yours to clear out — deleting the download rows from the
149+
management UI's Downloads page removes their files too.
150+
151+
## Management UI stuck on "Reconnecting…"
152+
153+
The Overview and Downloads pages show a **Live** badge while their
154+
[event stream](/guide/management-ui#live-updates) is connected. If it sits on
155+
**Reconnecting…** — or flips to it every few seconds — the stream is being
156+
closed or buffered before it reaches the browser. The pages still load; they
157+
just stop updating on their own.
158+
159+
Three usual causes:
160+
161+
- **A reverse proxy is buffering the response.** SSE only works if the proxy
162+
streams bytes through. jack sends `X-Accel-Buffering: no` and the UI's BFF
163+
forwards it, which nginx honours; for others turn buffering off explicitly
164+
(`proxy_buffering off;` on nginx, `flush_interval = -1` on Traefik, Caddy's
165+
`reverse_proxy` streams by default).
166+
- **The proxy's idle timeout is too short.** Streams are idle between changes,
167+
with only a `ping` every 15 seconds. Give the UI route a read/idle timeout
168+
well above that — 60 seconds or more.
169+
- **The management API is down or unreachable.** The BFF answers `503` when it
170+
can't reach jack. Check `docker compose ps` and the backend logs for
171+
`Management API listening`.
172+
129173
## Seeing what jack is doing
130174

131175
Set `LOG_LEVEL=trace` to log every HTTP request (method, path, status,

‎website/index.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ features:
3434
details: No trackers, no swarm — files transfer over plain, authenticated HTTP.
3535
- icon: 🖥️
3636
title: Web management console
37-
details: Manage servers, peers, API keys, and downloads without hand-editing config files.
37+
details: Manage servers, peers, API keys, and downloads without hand-editing config files — transfers and connector state update live.
3838
---

0 commit comments

Comments
 (0)