diff --git a/tools/observer/observer.mjs b/tools/observer/observer.mjs index e46ff961..8db92d5b 100644 --- a/tools/observer/observer.mjs +++ b/tools/observer/observer.mjs @@ -440,6 +440,9 @@ async function flushChain() { } async function tick(rpc) { + try { await tickInner(rpc); rpc.noteTick && rpc.noteTick(true); } catch (e) { rpc.noteTick && rpc.noteTick(false); } +} +async function tickInner(rpc) { const now = Date.now(); let dag, info, peersRes, hps; try { @@ -449,7 +452,7 @@ async function tick(rpc) { rpc.call('getConnectedPeerInfo', {}), rpc.call('estimateNetworkHashesPerSecond', { windowSize: 1000, startHash: null }).catch(() => null), ]); - } catch (e) { log('tick failed', e.message); return; } + } catch (e) { log('tick failed', e.message); throw e; } if (dag.network) network = String(dag.network).startsWith('igneum') ? dag.network : `igneum-${dag.network}`; nodeVersion = info.serverVersion || nodeVersion; if (dag.sink && dag.sink !== sinkHash) { sinkHash = dag.sink; pendingChain.add.add(dag.sink); } @@ -963,6 +966,20 @@ async function main() { }; rpc.onClose = () => { setTimeout(connect, 2000); }; await connect(); + // Watchdog (5 October 2026): after the observer node was restarted for 0.3.9 the reporter logged "rpc not connected" for + // an hour without reconnecting (the socket's close never resolved into a new connect). Ten failed ticks in a row force + // the socket shut and a fresh connect; the live page must never go stale while the node answers. + let failedTicks = 0; + rpc.noteTick = (ok) => { + failedTicks = ok ? 0 : failedTicks + 1; + if (failedTicks === 10) { + log('watchdog: 10 failed ticks, forcing a reconnect'); + failedTicks = 0; + try { rpc.ws && rpc.ws.close(); } catch { } + rpc.open = false; + setTimeout(connect, 1000); + } + }; setInterval(async () => { if (flushBusy) return; flushBusy = true; try { await flushBlocks(); await flushChain(); } finally { flushBusy = false; } }, FLUSH_EVERY_MS); setInterval(() => flushColors(rpc), FLUSH_EVERY_MS);