A partner's Emby URL is http://localhost:8096 — true there, meaningless here —
so nobody queries a partner's media server directly. Each host reports its own
over the SSH call remote_arr_cache_writer.sh already makes, which keeps its API
keys on it and costs no extra connection. Local is the default: opening the tab
to check your own server should not first make you read past a partner's.
A partner with no cache is stated as not collected rather than omitted, because
an empty mesh view and a partner that is down look identical otherwise.
The counts need the entire library downloaded to compute six numbers — 16.0 MB
from Radarr and 5.5 MB from Sonarr, measured — and they were on the same
one-minute clock as queue depth and health, which pulled ~30 GB a day out of the
arrs to re-count records that had not changed. They now cache for fifteen
minutes against how often the numbers actually move: 7.6s to 3.0s per refresh.
Emby and Jellyfin get a card each: version, CPU, memory, uptime, streams, users
and transcodes, with update/restart flags. Two halves of one question — a server
answering happily at 145% CPU is a different situation from one at 8%, and
neither the app nor the container says so alone.
The media jobs row I just added formats durations with _dur(), which the rsync
page defines locally and js/varaverk.js does not export at all. The reference
threw inside _render(), the fetch's catch reported it as "Error loading arrs
status", and the whole page went blank — nothing to do with the API, which was
returning valid JSON throughout.
play_state_sync, media_shares_permissions and media_cleaner work on the same
files the arrs manage and were visible only by opening the Scheduler and reading
an orchestrator's log. Readable at all because run_orch_child() now writes a run
record and a per-script log for its children — this could not have been written
yesterday. Each card shows the sentence the script itself ended on rather than a
count re-derived here, since the three word their outcome differently and the
wording is the part worth reading.
The arr cleanups are entries in DAILY_MAINTENANCE_SCRIPTS, which the orchestrator
invokes with plain bash, so they never get the run record the primary parse needs
— every payload has come from the daily aggregate db. That path read every column
except the byte counts, leaving orphans_sz at its "0B" default, which is
invisible at zero orphans and would have read "12 orphans (0B)" the first time
there were any. 'total' had no source there and no reader anywhere, so it is gone.
Arr Sync now reads "disabled" rather than "never run" when its switch is off.
Health messages go straight from each arr's API into innerHTML and quote things
nobody here controls — indexer names from Prowlarr, import-list names, release
titles. The page used no escaping at all. _sz() was also binary while labelling
its output TB, so /tv read 86.9 TB here and 95.6 TB on every other tab; it has
one caller and that caller is disk capacity, so it now matches the rest.
A multipart POST to the plugin API hangs and never completes on this host: no
status code, and no server-side trace of any kind. The correlation was exact —
every page using URLSearchParams worked, every page using FormData hung, which
is why scheduler and partnership appeared fine while docker, rsync, settings,
auth, arrs, fallback and monitor did not. URLSearchParams has the same append
API and fetch sets the urlencoded content type for it, so each site is a
one-token change with the payload logic untouched.
Unraid already enforces CSRF on every POST via auto_prepend, but its
injector is jQuery-only — the plugin's native fetch() calls carried no
token and were being terminated before the endpoint ran, silently,
because csrf_terminate exits with an empty body that r.json() swallows.
Documents each tab's purpose, what it renders, and which endpoints it polls.
Pages that start with markup get the header in a <?php ?> block so it never
reaches the browser.
Also corrects the layer diagram in README-unraid.md: eight of eleven pages hold
no PHP logic and poll api/ for everything — only auth, monitor and scheduler
require an include/ file directly.