Say fallback, not failover — the synonym was silently matching nothing in three renderers, plus retrying probes and a 2-minute handback window
This commit is contained in:
@@ -249,7 +249,7 @@ const VV_SCRIPT_CONF_SECTIONS = [
|
||||
'Arrs_Stack/arrs_failed_stalled_recovery.sh' => ['Arr Failed/Stalled Recovery', 'Arr Recovery Toggles'],
|
||||
'Media/play_state_sync.sh' => ['Play State Sync', 'Play State Sync — Handback'],
|
||||
'Orchestrators/sunday_morning_coffee_report.sh' => ['Sunday Morning Coffee Report'],
|
||||
'Fallback/fallback_test.sh' => ['Failover Test'],
|
||||
'Fallback/fallback_test.sh' => ['Fallback Test'],
|
||||
'Rsync/rsync.sh' => ['Rsync Enable/Disable', 'Rsync Defaults',
|
||||
'Rsync Profile System', 'Rsync Merge Auto-Promote'],
|
||||
'System_Essentials/server_reboot.sh' => ['Reboot', 'Emby'],
|
||||
|
||||
@@ -202,7 +202,9 @@ function vv_fallback_state(): array {
|
||||
}
|
||||
return vv_fb_card_extra() + [
|
||||
'state' => $raw['state'] ?? 'UNKNOWN',
|
||||
'failover_start' => $raw['failover_start'] ?? '0',
|
||||
// fallback_start, not failover_start. The state file has only ever written the former, so this
|
||||
// read returned '0' every time and the Monitor card's outage duration never rendered.
|
||||
'fallback_start' => $raw['fallback_start'] ?? '0',
|
||||
'tier2_started' => $raw['tier2_started'] ?? 'false',
|
||||
'tier3_started' => $raw['tier3_started'] ?? 'false',
|
||||
'tier4_started' => $raw['tier4_started'] ?? 'false',
|
||||
|
||||
@@ -223,7 +223,7 @@ if (vv_ai_ui_on()) vv_ai_chat_assets();
|
||||
<div class="vv-fb-ctrl-row">
|
||||
<div>
|
||||
<div class="vv-fb-ctrl-lbl">Fallback</div>
|
||||
<div class="vv-fb-ctrl-sub">Mutual container failover between nodes</div>
|
||||
<div class="vv-fb-ctrl-sub">Mutual container fallback between nodes</div>
|
||||
</div>
|
||||
<div class="vv-fb-tog" id="vv-fb-en-tog" onclick="vvFbToggle(this,'FALLBACK_ENABLED')"></div>
|
||||
</div>
|
||||
@@ -680,7 +680,7 @@ function _verdict(data) {
|
||||
if (!data.partnership_enabled)
|
||||
return void (el.innerHTML = '<span style="color:#ef5350;">PARTNERSHIP_ENABLED=false</span> — all cross-server operations are disabled.');
|
||||
if (!data.fb_enabled)
|
||||
return void (el.innerHTML = '<span style="color:#ffb74d;">FALLBACK_ENABLED=false</span> — nothing will fail over. Arming it takes effect at the next array start.');
|
||||
return void (el.innerHTML = '<span style="color:#ffb74d;">FALLBACK_ENABLED=false</span> — nothing will fall back. Arming it takes effect at the next array start.');
|
||||
|
||||
const inFb = nodes.filter(n => (n.state?.state) === 'FALLBACK');
|
||||
const live = nodes.filter(n => n.proc?.running && n.proc.mode === 'live');
|
||||
@@ -699,7 +699,7 @@ function _verdict(data) {
|
||||
: `<span style="color:#4caf50;">Armed</span> · ${up}/${nodes.length} node${nodes.length!==1?'s':''} running`;
|
||||
|
||||
if (dry.length && !live.length)
|
||||
s += ` — <span style="color:#4a9eff;">all previewing (dry run), nothing would actually fail over</span>`;
|
||||
s += ` — <span style="color:#4a9eff;">all previewing (dry run), nothing would actually fall back</span>`;
|
||||
else if (dry.length)
|
||||
s += ` · <span style="color:#4a9eff;">${dry.map(n=>n.id).join(', ')} previewing (dry run)</span>`;
|
||||
|
||||
@@ -898,7 +898,7 @@ window.vvFbSaveSettings = function() {
|
||||
};
|
||||
|
||||
|
||||
// ── Failover coverage picker ──────────────────────────────────────────────────
|
||||
// ── Fallback coverage picker ──────────────────────────────────────────────────
|
||||
// Holds the whole edit in memory and writes all four tiers in one POST. Per-row saves would
|
||||
// leave the four arrays briefly disagreeing, and fallback.sh reads them as a set.
|
||||
let _vvFbCov = null; // { containers:[], cover:{name:tier}, missing:[] }
|
||||
|
||||
@@ -1204,7 +1204,7 @@ function vvPollMonitor(live) {
|
||||
// ── State label + outage duration ──────────────────────────────────────
|
||||
let stateExtra = '';
|
||||
if (state === 'FALLBACK' || state === 'DARK') {
|
||||
const start = parseInt(fb.failover_start ?? 0);
|
||||
const start = parseInt(fb.fallback_start ?? 0);
|
||||
if (start > 0) {
|
||||
const sec = Math.floor(Date.now() / 1000) - start;
|
||||
stateExtra = ` · ${Math.floor(sec/3600)}h ${Math.floor((sec%3600)/60)}m`;
|
||||
@@ -1267,7 +1267,7 @@ function vvPollMonitor(live) {
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// ── Tier badges (FAILOVER only) ────────────────────────────────────────
|
||||
// ── Tier badges (FALLBACK only) ────────────────────────────────────────
|
||||
if (state === 'FALLBACK') {
|
||||
const t2 = fb.tier2_started === 'true';
|
||||
const t3 = fb.tier3_started === 'true';
|
||||
|
||||
@@ -710,14 +710,16 @@ function _renderConfig(cfg) {
|
||||
|
||||
const fbColors = {
|
||||
NORMAL: '#4caf50',
|
||||
FAILOVER: '#f44336',
|
||||
// FALLBACK — fallback.sh writes NORMAL|FALLBACK|NO_INTERNET|DARK and never 'FAILOVER', so
|
||||
// this entry matched nothing and a covering host rendered as UNKNOWN grey.
|
||||
FALLBACK: '#f44336',
|
||||
NO_INTERNET: '#ff9800',
|
||||
DARK: '#9e9e9e',
|
||||
UNKNOWN: '#444',
|
||||
};
|
||||
const fbLabels = {
|
||||
NORMAL: '✓ Nominal',
|
||||
FAILOVER: '⚠ Failover',
|
||||
FALLBACK: '⚠ Fallback active',
|
||||
NO_INTERNET: '⚡ No internet',
|
||||
DARK: '◌ Dark mode',
|
||||
UNKNOWN: '— Unknown',
|
||||
|
||||
@@ -679,7 +679,7 @@ $runningScripts = array_unique($runningScripts);
|
||||
<div class="vv-sug-body">
|
||||
<pre class="vv-readme-body">Not enterprise HA. No SLAs, no quorum nodes, no guaranteed uptime — don't put your billing system on this.
|
||||
|
||||
What it is: mutual automatic failover between two independent unRAID servers. When one goes down the other starts its containers, cuts over DNS, and keeps users online. When it comes back, everything hands back in the correct sequence — DDNS stops, containers stop, rsync writeback runs, containers start on the primary, primary DDNS starts last — so users hit the returning server only after it's actually ready.
|
||||
What it is: mutual automatic fallback between two independent unRAID servers. When one goes down the other starts its containers, cuts over DNS, and keeps users online. When it comes back, everything hands back in the correct sequence — DDNS stops, containers stop, rsync writeback runs, containers start on the primary, primary DDNS starts last — so users hit the returning server only after it's actually ready.
|
||||
|
||||
Built from scratch. Refined through a year of production testing. The DDNS sequencing and handback order were the hardest parts to get right. Both directions are exercised regularly with fallback_test.sh.</pre>
|
||||
</div>
|
||||
@@ -4967,7 +4967,7 @@ function vvPollSnapshot() {
|
||||
const s = (d.fallback ?? 'UNKNOWN').toUpperCase();
|
||||
fb.textContent = s;
|
||||
fb.style.color = s === 'NORMAL' ? '#4caf50'
|
||||
: s === 'FAILOVER' ? '#f44336'
|
||||
: s === 'FALLBACK' ? '#f44336' // never 'FAILOVER' — see fallback.sh state_set
|
||||
: s === 'NO_INTERNET' ? '#ff9800' : '#666';
|
||||
}
|
||||
const pt = document.getElementById('vv-snap-partner');
|
||||
|
||||
Reference in New Issue
Block a user