State-file age is time since the last transition, not staleness, and a preview's state is the one being decided

This commit is contained in:
Gmer4Lfe
2026-08-22 00:52:38 -04:00
parent 8454d3d0a2
commit 0f228020ef
2 changed files with 79 additions and 24 deletions
+35
View File
@@ -172,6 +172,30 @@ function vv_fb_remote_proc(string $ip, string $sshKey): array {
}
return $res;
}
// A running dry run keeps its own state file — VV_CACHE_ROOT/fallback_state.dryrun.<pid> — and
// refreshes it every check interval, exactly as the live daemon would. Reading the LIVE file
// while a preview is running is how a healthy dry run came to render as UNKNOWN on a host that
// has simply never run fallback for real: the answer existed, in a file next to the one being
// read. The preview is shown as the preview, never merged into the live state.
function vv_fb_dryrun_state(int $pid): array {
$p = (VV_CACHE_ROOT ?: '/tmp/varaverk') . '/fallback_state.dryrun.' . $pid;
if (!is_file($p)) return ['state' => null, 'age' => null];
$s = vv_fb_parse_state((string)@file_get_contents($p));
$s['age'] = time() - (int)@filemtime($p);
return $s;
}
function vv_fb_remote_dryrun_state(string $ip, string $sshKey, int $pid): array {
$f = '/tmp/varaverk/fallback_state.dryrun.' . $pid;
$out = vv_pt_ssh($ip, $sshKey, "[ -f '$f' ] && { echo \"__age=\$(( \$(date +%s) - \$(stat -c %Y '$f') ))\"; cat '$f'; }");
if (trim((string)$out) === '') return ['state' => null, 'age' => null];
$age = null;
if (preg_match('/^__age=(\d+)/m', (string)$out, $m)) $age = (int)$m[1];
$s = vv_fb_parse_state((string)$out);
$s['age'] = $age;
return $s;
}
// ── Covers — what a node runs for the other when it's down ───────────────────
function vv_fb_covers(string $covering, string $remote, string $coveringRaw, string $remoteRaw): array {
@@ -279,6 +303,16 @@ function vv_fb_all(): array {
$procTest = ['running' => null, 'pid' => null, 'mode' => null, 'stale_lock' => false];
}
// When a preview is running, read what IT is deciding — kept beside the live file and
// refreshed on the same interval. Reported separately so the live state is never
// overwritten by a preview's opinion.
$preview = ['state' => null, 'age' => null];
if (($proc['mode'] ?? '') === 'dry-run' && !empty($proc['pid'])) {
$preview = $isMe
? vv_fb_dryrun_state((int)$proc['pid'])
: vv_fb_remote_dryrun_state($ip, $mySshKey, (int)$proc['pid']);
}
// How fresh the state actually is. The daemon rewrites its file every check interval, so
// an age far past that interval means it is wedged even while the process still exists.
$stateAge = null;
@@ -304,6 +338,7 @@ function vv_fb_all(): array {
'ts_ip' => $ip,
'state' => $state,
'state_age' => $stateAge,
'preview' => $preview,
'running' => $running,
'running_count' => count($running),
'proc' => $proc,