bin.js: exit on dead sbot connection instead of wedging
ssb-viewer holds one muxrpc handle captured in a closure and has no reconnect path. When sbot is OOM-killed and restarted by run-server.sh, the viewer kept port 8807 open while holding a dead connection and never answered again -- the silent wedge. Listen for muxrpc closed and exit(1) so the while-loop in run-ssb-viewer.sh restarts with a fresh connection. Also poll whoami to catch half-open connections where closed never fires. Verified: killing sbot now self-heals in ~4s instead of hanging.
This commit is contained in:
@@ -1,6 +1,49 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
// ssb-viewer connects to sbot exactly once and hands the handle to index.js,
|
||||||
|
// which captures it in a closure behind http.createServer().listen(). There is
|
||||||
|
// no reconnect. So when sbot dies -- which on this box means "gets OOM-killed",
|
||||||
|
// after which run-server.sh restarts it -- the viewer keeps port 8807 open
|
||||||
|
// while holding a dead muxrpc connection, and never answers another request.
|
||||||
|
//
|
||||||
|
// That is the silent wedge. The fix is not to reconnect (index.js can't take a
|
||||||
|
// new handle) but to exit loudly, so the `while true` loop in run-ssb-viewer.sh
|
||||||
|
// restarts us with a fresh connection.
|
||||||
|
|
||||||
|
var PING_INTERVAL_MS = 60000
|
||||||
|
var PING_TIMEOUT_MS = 20000
|
||||||
|
|
||||||
|
function bail (why) {
|
||||||
|
console.error('[viewer] ' + new Date().toISOString() + ' ' + why + ' — exiting so the run loop restarts us')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
require('ssb-client')(function (err, sbot, config) {
|
require('ssb-client')(function (err, sbot, config) {
|
||||||
if (err) throw err
|
// ssb-client already wraps this as "could not connect to sbot", so don't
|
||||||
|
// prefix it again.
|
||||||
|
if (err) return bail(String(err.message || err))
|
||||||
|
|
||||||
|
// muxrpc emits 'closed' when the underlying stream ends
|
||||||
|
// (see node_modules/muxrpc/index.js). This is the fast path.
|
||||||
|
sbot.on('closed', function () {
|
||||||
|
bail('sbot connection closed')
|
||||||
|
})
|
||||||
|
|
||||||
|
// Belt and braces: a half-open TCP connection can leave 'closed' unfired
|
||||||
|
// while calls silently hang forever. Poll a cheap RPC to catch that case.
|
||||||
|
if (typeof sbot.whoami === 'function') {
|
||||||
|
var timer = setInterval(function () {
|
||||||
|
var timeout = setTimeout(function () {
|
||||||
|
bail('sbot did not answer whoami within ' + (PING_TIMEOUT_MS / 1000) + 's')
|
||||||
|
}, PING_TIMEOUT_MS)
|
||||||
|
sbot.whoami(function (err) {
|
||||||
|
clearTimeout(timeout)
|
||||||
|
if (err) bail('sbot whoami failed: ' + (err.message || err))
|
||||||
|
})
|
||||||
|
}, PING_INTERVAL_MS)
|
||||||
|
// Don't hold the event loop open on our account.
|
||||||
|
timer.unref()
|
||||||
|
}
|
||||||
|
|
||||||
require('.').init(sbot, config)
|
require('.').init(sbot, config)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user