diff --git a/lib/heartbeat.js b/lib/heartbeat.js index 885a435bf49992602862a397e9abe4fb5dab085a..36c1b13e8ac6fddef4509e4cefb76e1c9974e038 100644 --- a/lib/heartbeat.js +++ b/lib/heartbeat.js @@ -10,6 +10,8 @@ url = require('url'); // the path that heartbeats live at exports.path = '/__heartbeat__'; +const checkTimeout = 10000; + // a helper function to set up a heartbeat check exports.setup = function(app, options, cb) { var dependencies = []; @@ -22,61 +24,61 @@ exports.setup = function(app, options, cb) { var count = dependencies.length; app.use(function(req, res, next) { - if (req.method === 'GET' && req.path === exports.path) { - var checked = 0; - var query = url.parse(req.url, true).query; - var deep = typeof query.deep != 'undefined'; - var notOk = []; + if (req.method !== 'GET' || req.path !== exports.path) { + return next(); + } - // callback for checking a dependency - function checkCB (num) { - return function (isOk) { - checked++; - if (!isOk) { - notOk.push(dependencies[num]); - } + var checked = 0; + var query = url.parse(req.url, true).query; + var deep = typeof query.deep != 'undefined'; + var notOk = []; - // if all dependencies have been checked - if (checked == count) { - if (notOk.length === 0) { - try { - if (cb) cb(ok); - else ok(true); - } catch(e) { - logger.error("Exception caught in heartbeat handler: " + e.toString()); - ok(false, e); - } - } else { - logger.error("Not all dependencies available"); - ok(false, notOk.join(': failed\n') + ': failed'); + // callback for checking a dependency + function checkCB (num) { + return function (isOk, reason) { + checked++; + if (!isOk) { + notOk.push(dependencies[num] + ': '+ reason); + } + + // if all dependencies have been checked + if (checked == count) { + if (notOk.length === 0) { + try { + if (cb) cb(ok); + else ok(true); + } catch(e) { + logger.error("Exception caught in heartbeat handler: " + e.toString()); + ok(false, e); } + } else { + logger.error("Not all dependencies are available"); + ok(false, '\n' + notOk.join('\n') + '\n'); } - }; - } + } + }; + } - function ok(yeah, msg) { - res.writeHead(yeah ? 200 : 500); - res.write(yeah ? 'ok' : 'bad'); - if (msg) res.write(msg); - res.end(); - } + function ok(yeah, msg) { + res.writeHead(yeah ? 200 : 500); + res.write(yeah ? 'ok' : 'bad'); + if (msg) res.write(msg); + res.end(); + } - // check all dependencies if deep - if (deep) { - for (var i = 0; i < count; i++) { - check(dependencies[i] + exports.path, checkCB(i)); - } - } else { - try { - if (cb) cb(ok); - else ok(true); - } catch(e) { - logger.error("Exception caught in heartbeat handler: " + e.toString()); - ok(false); - } + // check all dependencies if deep + if (deep) { + for (var i = 0; i < count; i++) { + check(dependencies[i] + exports.path, checkCB(i)); } } else { - return next(); + try { + if (cb) cb(ok); + else ok(true); + } catch(e) { + logger.error("Exception caught in heartbeat handler: " + e.toString()); + ok(false); + } } }); }; @@ -90,15 +92,26 @@ var check = exports.check = function(url, cb) { var shortname = url.host + ':' + url.port; - require(url.scheme).get({ + var req = require(url.scheme).get({ host: url.host, port: url.port, path: exports.path }, function (res) { if (res.statusCode === 200) cb(true); - else logger.error("non-200 response from " + shortname + ". fatal! (" + res.statusCode + ")"); - }, function (e) { + else { + logger.error("non-200 response from " + shortname + ". fatal! (" + res.statusCode + ")"); + cb(false, "response code " + res.statusCode); + } + }); + req.on('error', function (e) { logger.error("can't communicate with " + shortname + ". fatal: " + e); - cb(false); + cb(false, e); + }); + req.on('connect', function (socket) { + socket.setTimeout(checkTimeout); + socket.on('timeout', function() { + req.abort(); + cb(false, "timeout"); + }); }); };