Enhanced state handling
This commit is contained in:
54
installer
54
installer
@ -405,6 +405,10 @@ $stratum = 'stratum+tcp://' . $host . ':3333';
|
||||
const syncTracker = { samples: [] };
|
||||
const WINDOW_SECONDS = 900; // 15 minutes
|
||||
|
||||
// 30-second heartbeat
|
||||
let lastStatusOk = Date.now(); // timestamp of last good fetch
|
||||
const STALE_MS = 30000; // 30 seconds
|
||||
|
||||
function formatEta(seconds) {
|
||||
if (seconds == null || !isFinite(seconds)) return 'estimating…';
|
||||
if (seconds < 60) return seconds.toFixed(0) + 's';
|
||||
@ -457,13 +461,15 @@ async function loadStatus() {
|
||||
const res = await fetch('/status.php', {cache: 'no-store'});
|
||||
const data = await res.json();
|
||||
const box = document.getElementById('node-status');
|
||||
const rawIbd = data.initialblockdownload;
|
||||
const hasRealIbd = (typeof rawIbd === 'boolean');
|
||||
|
||||
if (data.error) {
|
||||
box.innerHTML = '<h2>Status</h2><p class="status-err">' + data.error + '</p>' + renderServices(data.services);
|
||||
return;
|
||||
}
|
||||
|
||||
const ibd = !!data.initialblockdownload;
|
||||
const ibd = hasRealIbd ? rawIbd : true; // default to "syncing/problem" if unknown
|
||||
const blocks = data.blocks ?? '–';
|
||||
const pruned = data.pruned ? '(pruned)' : '';
|
||||
let progress = 0;
|
||||
@ -474,15 +480,32 @@ async function loadStatus() {
|
||||
}
|
||||
|
||||
// Update favicon dynamically
|
||||
setFaviconAndTitle(ibd, progress);
|
||||
lastStatusOk = Date.now();
|
||||
const bitcoindActive = data.services && data.services.bitcoind === 'active';
|
||||
if (!bitcoindActive) {
|
||||
setFaviconAndTitle(false, 0, true); // show Disconnected
|
||||
} else {
|
||||
setFaviconAndTitle(ibd, progress, false);
|
||||
}
|
||||
|
||||
// update window + estimate
|
||||
updateSamples(progress);
|
||||
const etaSeconds = ibd ? estimateEta(progress) : null;
|
||||
|
||||
let html = '<h2>Status</h2>';
|
||||
|
||||
if (ibd) {
|
||||
if (!hasRealIbd) {
|
||||
if (data.services && data.services.bitcoind === 'active') {
|
||||
html += '<p class="status-err">❌ Cannot read Bitcoin Core status. If this persists, try refreshing your browser.</p>';
|
||||
} else {
|
||||
html += '<p class="status-err">❌ Bitcoin service is not running.</p>';
|
||||
}
|
||||
} else if (!bitcoindActive) {
|
||||
// technically covered above, but keep explicit
|
||||
html += '<p class="status-err">❌ Bitcoin service is not running.</p>';
|
||||
} else if (ibd && progress < 0.1) {
|
||||
// active but no real progress yet
|
||||
html += '<p class="status-warn">⚠ Bitcoin Core is starting up and loading blockchain data. Please wait...</p>';
|
||||
} else if (ibd) {
|
||||
html += '<p class="status-warn">⚠ Bitcoin Core is syncing. Your miners will not be able to submit shares or receive work until the node is fully synced.</p>';
|
||||
} else {
|
||||
html += '<p class="status-ok">✔ Bitcoin Core is in sync.</p>';
|
||||
@ -519,27 +542,44 @@ async function loadStatus() {
|
||||
} catch (e) {
|
||||
const box = document.getElementById('node-status');
|
||||
box.innerHTML = '<h2>Status</h2><p class="status-err">Failed to fetch status.</p>';
|
||||
setFaviconAndTitle(false, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Inline SVG favicons
|
||||
const FAV_SYNC = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='64' height='64'%3E%3Crect width='64' height='64' fill='%23222'/%3E%3Ctext x='50%25' y='55%25' text-anchor='middle' font-size='32' fill='%23ffb347'%3E%E2%9A%A0%3C/text%3E%3C/svg%3E";
|
||||
const FAV_READY = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='64' height='64'%3E%3Crect width='64' height='64' fill='%23161717'/%3E%3Ctext x='50%25' y='55%25' text-anchor='middle' font-size='34' fill='%238f8'%3E%E2%9C%94%3C/text%3E%3C/svg%3E";
|
||||
const FAV_ERR = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='64' height='64'%3E%3Crect width='64' height='64' fill='%23222222'/%3E%3Ctext x='50%25' y='55%25' text-anchor='middle' font-size='34' fill='%23ff6b6b'%3E!%3C/text%3E%3C/svg%3E";
|
||||
|
||||
function setFaviconAndTitle(isSyncing, progress) {
|
||||
function setFaviconAndTitle(isSyncing, progress, isError = false) {
|
||||
const link = document.getElementById('app-favicon');
|
||||
if (!link) return;
|
||||
if (isError) {
|
||||
link.href = FAV_ERR;
|
||||
document.title = "Disconnected • Bitcoin Solo Miner";
|
||||
return;
|
||||
}
|
||||
if (isSyncing) {
|
||||
link.href = FAV_SYNC;
|
||||
document.title = "Syncing… " + progress.toFixed(1) + "% | Bitcoin Node";
|
||||
document.title = "Syncing… " + progress.toFixed(1) + "% | Bitcoin Solo Miner";
|
||||
} else {
|
||||
link.href = FAV_READY;
|
||||
document.title = "Ready • Bitcoin Node";
|
||||
document.title = "Ready • Bitcoin Solo Miner";
|
||||
}
|
||||
}
|
||||
|
||||
loadStatus();
|
||||
setInterval(loadStatus, 5000);
|
||||
setInterval(() => {
|
||||
if (Date.now() - lastStatusOk > STALE_MS) {
|
||||
// no successful poll in 30s -> error state
|
||||
setFaviconAndTitle(false, 0, true);
|
||||
const box = document.getElementById('node-status');
|
||||
if (box && !box.innerHTML.includes('Failed to fetch')) {
|
||||
box.innerHTML = '<h2>Status</h2><p class="status-err">Status information unavailable (stale data > 30s). If this persists, try refreshing your browser.</p>';
|
||||
}
|
||||
}
|
||||
}, 3000);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user