Partnership page: one settings card instead of three, and a Data Transferred card
Windows with runs but no bytes say 'no data moved' rather than 0.00 GB, and rows before the byte-parser fix are excluded rather than summed into a false total.
This commit is contained in:
@@ -240,6 +240,72 @@ function vv_pt_remote_system(string $ip, string $sshKey): array {
|
||||
];
|
||||
}
|
||||
|
||||
// ── Transfer volume ───────────────────────────────────────────────────────────
|
||||
//
|
||||
// Reads data/db/bandwidth_history.db, one line per completed rsync:
|
||||
// YYYY-MM-DD|HH:MM|profile|duration|status|bytes
|
||||
//
|
||||
// Rows before VV_BW_EPOCH are excluded outright. Until 2026-08-14 rsync.sh read the byte count
|
||||
// from the wrong field of rsync --stats and every row was written as 0 — 1,423 of them. Summing
|
||||
// those produces a confident 0.00 GB for any window that reaches back far enough, which is worse
|
||||
// than an empty card: it is a measurement that looks taken. The cut is on the fix, not on a
|
||||
// guess about which rows look plausible.
|
||||
//
|
||||
// A window whose rows are all zero reports null, not 0, so the UI can say "no transfers
|
||||
// recorded" rather than assert nothing moved. Those are different claims and only one of them
|
||||
// is supported by an all-zero column.
|
||||
define('VV_BW_EPOCH', '2026-08-14');
|
||||
|
||||
function vv_pt_transfer_stats(): array {
|
||||
$file = DATA_DIR . '/db/bandwidth_history.db';
|
||||
$out = ['epoch' => VV_BW_EPOCH, 'windows' => [], 'live' => null, 'usable_rows' => 0];
|
||||
|
||||
$windows = ['24h' => 86400, '7d' => 604800, '30d' => 2592000];
|
||||
foreach ($windows as $k => $_) $out['windows'][$k] = ['bytes' => null, 'runs' => 0, 'failed' => 0];
|
||||
|
||||
if (is_file($file)) {
|
||||
$now = time();
|
||||
$epoch = strtotime(VV_BW_EPOCH . ' 00:00:00');
|
||||
$fh = fopen($file, 'r');
|
||||
if ($fh) {
|
||||
while (($line = fgets($fh)) !== false) {
|
||||
$p = explode('|', trim($line));
|
||||
if (count($p) < 6) continue;
|
||||
$ts = strtotime($p[0] . ' ' . $p[1]);
|
||||
if (!$ts || $ts < $epoch) continue;
|
||||
$out['usable_rows']++;
|
||||
$bytes = (int)$p[5];
|
||||
$failed = ($p[4] ?? '') !== 'success';
|
||||
foreach ($windows as $k => $span) {
|
||||
if ($ts < $now - $span) continue;
|
||||
$w = &$out['windows'][$k];
|
||||
$w['runs']++;
|
||||
if ($failed) $w['failed']++;
|
||||
if ($bytes > 0) $w['bytes'] = (int)$w['bytes'] + $bytes;
|
||||
unset($w);
|
||||
}
|
||||
}
|
||||
fclose($fh);
|
||||
}
|
||||
}
|
||||
|
||||
// Live: an rsync this host is running right now. The lock name carries the share, which is
|
||||
// the only part of "what is moving" worth showing without parsing progress output.
|
||||
$running = trim((string)shell_exec("pgrep -c -f '^rsync -av' 2>/dev/null")) ;
|
||||
if ((int)$running > 0) {
|
||||
$share = '';
|
||||
foreach (glob('/tmp/unraid_locks/rsync_*.lock') ?: [] as $l) {
|
||||
$pid = (int)preg_replace('/\D/', '', (string)@file_get_contents($l));
|
||||
if ($pid && is_dir("/proc/$pid")) {
|
||||
$share = preg_replace('/^rsync_|\.lock$/', '', basename($l));
|
||||
break;
|
||||
}
|
||||
}
|
||||
$out['live'] = ['running' => (int)$running, 'share' => $share];
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
// ── Media seed progress ───────────────────────────────────────────────────────
|
||||
//
|
||||
// Phase 3 dispatches Rsync/media_seed.sh detached, because a first seed of a full
|
||||
@@ -501,6 +567,7 @@ function vv_partnership_all(): array {
|
||||
'config' => vv_pt_config(),
|
||||
'nodes' => vv_pt_nodes(),
|
||||
'sync' => vv_pt_sync(),
|
||||
'xfer' => vv_pt_transfer_stats(),
|
||||
'ts' => time(),
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user