Show orphan and junk sizes, and drop a cleanup field nothing could fill
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.
This commit is contained in:
@@ -174,14 +174,37 @@ function vv_fetch_arr_live(array $arr): array {
|
||||
|
||||
// ── Log stats ─────────────────────────────────────────────────────────────────
|
||||
|
||||
// Bytes → a short human string, matching the shape the log SUMMARY already produces ("1.4G") so
|
||||
// the two sources of orphans_sz read alike rather than one saying "1.4G" and the other "1.4 GB".
|
||||
//
|
||||
// Decimal, like every other capacity figure in the plugin — see _sz() in js/varaverk.js and
|
||||
// _vv_api_fs_gb() in include/unraid_api.php for the same choice made on the other two sides.
|
||||
function vv_arr_fmt_bytes(int $b): string {
|
||||
if ($b <= 0) return '0B';
|
||||
if ($b >= 1e12) return round($b / 1e12, 1) . 'T';
|
||||
if ($b >= 1e9) return round($b / 1e9, 1) . 'G';
|
||||
if ($b >= 1e6) return round($b / 1e6) . 'M';
|
||||
if ($b >= 1e3) return round($b / 1e3) . 'K';
|
||||
return $b . 'B';
|
||||
}
|
||||
|
||||
function vv_arr_cleanup_stats(string $type): array {
|
||||
$slugs = ['sonarr' => 'Arrs_Stack/sonarr_cleanup',
|
||||
'radarr' => 'Arrs_Stack/radarr_cleanup',
|
||||
'lidarr' => 'Arrs_Stack/lidarr_cleanup'];
|
||||
$base = LOG_DIR . '/' . ($slugs[$type] ?? '');
|
||||
// 'total' is gone: nothing populated it on the path that actually runs, and no consumer ever
|
||||
// read it. It came from the log SUMMARY's "Tracked: N files (M total)", which the daily
|
||||
// aggregate has no equivalent for — so it was null in every payload this page has ever served.
|
||||
//
|
||||
// orphans_sz was in the same position — carried and never rendered — which is why nobody
|
||||
// noticed it was stuck at its default. It stays, and the page now shows it, because a count
|
||||
// of orphans is not actionable and a size is: 12 orphans is a shrug, 12 orphans at 400GB is
|
||||
// an afternoon.
|
||||
$out = ['last_run' => null, 'end' => null, 'status' => null,
|
||||
'tracked' => null, 'total' => null,
|
||||
'orphans' => 0, 'orphans_sz' => '0B', 'junk' => 0];
|
||||
'tracked' => null,
|
||||
'orphans' => 0, 'orphans_sz' => '0B',
|
||||
'junk' => 0, 'junk_sz' => '0B'];
|
||||
|
||||
$jf = $base . '.json';
|
||||
if (file_exists($jf)) {
|
||||
@@ -196,9 +219,8 @@ function vv_arr_cleanup_stats(string $type): array {
|
||||
$parts = preg_split('/━{3,}[^\n]*SUMMARY[^\n]*/u', $log);
|
||||
$blk = count($parts) > 1 ? end($parts) : $log;
|
||||
|
||||
if (preg_match('/Tracked:\s*([\d,]+)\s*files\s*\(([\d,]+)/u', $blk, $m)) {
|
||||
if (preg_match('/Tracked:\s*([\d,]+)\s*files/u', $blk, $m)) {
|
||||
$out['tracked'] = (int)str_replace(',', '', $m[1]);
|
||||
$out['total'] = (int)str_replace(',', '', $m[2]);
|
||||
}
|
||||
if (preg_match('/Orphans:\s*([\d,]+)\s*files\s*\(([^)]+)\)/u', $blk, $m)) {
|
||||
$out['orphans'] = (int)str_replace(',', '', $m[1]);
|
||||
@@ -210,7 +232,17 @@ function vv_arr_cleanup_stats(string $type): array {
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: daily aggregate db — date|arr|orphan_count|orphan_bytes|junk_count|junk_bytes|recent_count|tracked_count
|
||||
// Daily aggregate db — date|arr|orphan_count|orphan_bytes|junk_count|junk_bytes|recent_count|tracked_count
|
||||
//
|
||||
// Called the fallback, and it is in fact the only path that ever runs. The block above needs
|
||||
// LOG_DIR/Arrs_Stack/<type>_cleanup.json, which run_job.sh writes for a top-level job — and
|
||||
// the cleanups are not top-level jobs. They are entries in DAILY_MAINTENANCE_SCRIPTS, which
|
||||
// daily_sync_maintenance.sh invokes with plain `bash`, so their output lands inside the
|
||||
// orchestrator's log and no run record is written for them at all.
|
||||
//
|
||||
// The block above is therefore live only when someone runs a cleanup by hand from the
|
||||
// Scheduler tab, which does go through run_job.sh. It is kept for that case rather than
|
||||
// deleted, but on the nightly path everything below is what the page shows.
|
||||
if ($out['last_run'] === null) {
|
||||
$dbFile = DB_DIR . '/arr_cleanup_stats.db';
|
||||
if (file_exists($dbFile)) {
|
||||
@@ -225,6 +257,13 @@ function vv_arr_cleanup_stats(string $type): array {
|
||||
$out['orphans'] = (int)$last[2];
|
||||
$out['junk'] = (int)$last[4];
|
||||
$out['tracked'] = (int)$last[7];
|
||||
// Sizes were being dropped on the floor. The db records orphan_bytes beside the
|
||||
// count and this read every column except that one, so orphans_sz kept its '0B'
|
||||
// default — which is invisible today at zero orphans and would have read "12
|
||||
// orphans (0B)" the first time there were any, on the one number that decides
|
||||
// whether it is worth acting on.
|
||||
$out['orphans_sz'] = vv_arr_fmt_bytes((int)$last[3]);
|
||||
$out['junk_sz'] = vv_arr_fmt_bytes((int)$last[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ function _arrCard(arr) {
|
||||
<span class="vv-arr-meta-val">${_relTime(cl.last_run)} ${st}</span>
|
||||
</div>
|
||||
${cl.tracked != null ? `<div class="vv-arr-meta-sub" style="${orCol}">
|
||||
${_n(cl.tracked)} files · ${orph} orphans${junk ? ' · ' + junk + ' junk' : ''}
|
||||
${_n(cl.tracked)} files · ${orph} orphans${orph && cl.orphans_sz && cl.orphans_sz !== '0B' ? ' (' + vvEscHtml(cl.orphans_sz) + ')' : ''}${junk ? ' · ' + junk + ' junk' + (cl.junk_sz && cl.junk_sz !== '0B' ? ' (' + vvEscHtml(cl.junk_sz) + ')' : '') : ''}
|
||||
</div>` : ''}`;
|
||||
}
|
||||
|
||||
@@ -326,11 +326,14 @@ function _nodeSection(node) {
|
||||
|
||||
// ── Sync + Recovery row ───────────────────────────────────────────────────────
|
||||
function _syncSection(sync, recovery, settings) {
|
||||
const _card = (title, data, items, extra) => {
|
||||
// offTxt distinguishes "has not happened yet" from "cannot happen". Both render with no run
|
||||
// history, and "never run" on a switched-off subsystem reads as a fault waiting to clear —
|
||||
// it says the thing has not got round to it, when in fact it has been told not to.
|
||||
const _card = (title, data, items, extra, offTxt) => {
|
||||
const ok = data.last_run && data.status === 'ok';
|
||||
const bad = data.last_run && data.status !== 'ok';
|
||||
const pillCls = !data.last_run ? 'off' : ok ? 'ok' : 'err';
|
||||
const pillTxt = !data.last_run ? 'never run' : ok ? 'ok' : data.status || 'error';
|
||||
const pillTxt = !data.last_run ? (offTxt || 'never run') : ok ? 'ok' : data.status || 'error';
|
||||
let body = '';
|
||||
if (data.last_run) {
|
||||
body += `<div style="font-size:11px;color:#555;margin-bottom:10px;">${_relTime(data.last_run)}</div>`;
|
||||
@@ -359,14 +362,14 @@ function _syncSection(sync, recovery, settings) {
|
||||
? _item(`<span style="color:#6fcf97">+${_n(sync.added)}</span>`, 'Added') +
|
||||
(sync.nodes != null ? _item(_n(sync.nodes), 'Nodes') : '') +
|
||||
(sync.blocklist_count != null ? _item(_n(sync.blocklist_count), 'Blocklist') : '')
|
||||
: `<span style="color:#333;font-size:11px;">No run history</span>`;
|
||||
: `<span style="color:#333;font-size:11px;">${syncEnabled ? 'No run history' : 'Nothing to show while disabled'}</span>`;
|
||||
|
||||
const recItems = recovery.last_run
|
||||
? _item(_n(recovery.fixed), 'Fixed') + _item(_n(recovery.searched), 'Re-searched')
|
||||
: `<span style="color:#333;font-size:11px;">No run history</span>`;
|
||||
|
||||
return `<div class="vv-arr-sr-grid">
|
||||
${_card('Arr Sync', sync, syncItems, syncExtra)}
|
||||
${_card('Arr Sync', sync, syncItems, syncExtra, syncEnabled ? null : 'disabled')}
|
||||
${_card('Failed / Stalled Recovery', recovery, recItems, '')}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user