cluster-service
Advanced tools
Comparing version 0.2.2 to 0.2.3
@@ -7,2 +7,4 @@ var | ||
path = require("path"), | ||
httpserver = require("./lib/http-server"), | ||
cli = null, | ||
locals = { | ||
@@ -24,3 +26,4 @@ events: {}, | ||
allowHttpGet: false, // useful for testing -- not safe for production use | ||
restartsPerMinute: 10 // not yet supported | ||
restartsPerMinute: 10, // not yet supported | ||
cliEnabled: true | ||
} | ||
@@ -34,3 +37,9 @@ } | ||
if (cluster.isMaster) { | ||
startMaster(workerPath, options, cb); | ||
var first_req = true; | ||
startMaster(workerPath, options, function() { | ||
if (first_req === true) { // make sure we only cb once... | ||
first_req = false; | ||
cb && cb(); | ||
} | ||
}); | ||
} else { | ||
@@ -43,8 +52,24 @@ // only load worker for on worker processes | ||
exports.stop = function(timeout) { | ||
exports.stop = function(timeout, cb) { | ||
if (locals.state === 0) { | ||
throw "Must be running"; | ||
return; | ||
} | ||
exports.trigger("exit", timeout); | ||
if (exports.workers.length > 0) { // issue shutdown | ||
exports.trigger("shutdown", function() { | ||
httpserver.close(); | ||
if (cli) { | ||
process.exit(1); | ||
} else { | ||
cb && cb(); | ||
} | ||
}, "all", timeout); | ||
} else { // gracefully shutdown | ||
httpserver.close(); | ||
if (cli) { | ||
process.exit(1); | ||
} else { | ||
cb && cb(); | ||
} | ||
} | ||
}; | ||
@@ -58,2 +83,5 @@ | ||
overwriteExisting = overwriteExisting || true; | ||
if (!overwriteExisting && eventName in locals.events) { | ||
return; // do not overwrite existing | ||
} | ||
@@ -73,3 +101,3 @@ var evt = { | ||
if (locals.state === 0) { | ||
throw "Must be running"; | ||
throw new Error("Must be running"); | ||
} | ||
@@ -79,3 +107,3 @@ | ||
if (!evt) { | ||
throw "Event " + eventName + " not found"; | ||
throw new Error("Event " + eventName + " not found"); | ||
} | ||
@@ -89,3 +117,3 @@ | ||
} | ||
//console.log("trigger." + eventName + ".args=" + args.length); | ||
// invoke event callback | ||
@@ -97,3 +125,3 @@ return evt.cb.apply(null, args); | ||
if (cluster.isMaster === true) { | ||
throw "Cannot call workerReady from master..."; | ||
throw new Error("Cannot call workerReady from master..."); | ||
} | ||
@@ -119,3 +147,11 @@ | ||
get: function() { | ||
return cluster.workers; | ||
var workers = []; | ||
var cworkers = cluster.workers; | ||
for (var k in cworkers) { | ||
var worker = cworkers[k]; | ||
worker.pid = worker.process.pid; | ||
workers.push(worker); | ||
} | ||
return workers; | ||
} | ||
@@ -224,4 +260,7 @@ }); | ||
// wire-up CLI | ||
require("./lib/cli").init(locals, options); | ||
if (options.cliEnabled === true) { | ||
// wire-up CLI | ||
cli = require("./lib/cli"); | ||
cli.init(locals, options); | ||
} | ||
} | ||
@@ -235,2 +274,3 @@ | ||
} | ||
locals.startRequests = []; | ||
}); | ||
@@ -294,3 +334,3 @@ | ||
function startListener(options, cb) { | ||
require("./lib/http-server").init(locals, options, function(err) { | ||
httpserver.init(locals, options, function(err) { | ||
if (!err) { | ||
@@ -297,0 +337,0 @@ console.log("cluster-service is listening at " + options.host + ":" + options.port); |
@@ -17,2 +17,9 @@ var | ||
exports.close = function() { | ||
try { | ||
rl.close(); | ||
} catch (ex) { | ||
} | ||
}; | ||
function onCommand(question) { | ||
@@ -19,0 +26,0 @@ var args = require("./util").getArgsFromQuestion(question, " "); |
@@ -7,3 +7,4 @@ var | ||
locals = {}, | ||
options = null | ||
options = null, | ||
server = null | ||
; | ||
@@ -15,3 +16,3 @@ | ||
var server = locals.http = http.createServer(processRequest); | ||
server = locals.http = http.createServer(processRequest); | ||
@@ -23,2 +24,9 @@ server.on("error", cb); | ||
exports.close = function() { | ||
try { | ||
server.close(); | ||
} catch (ex) { | ||
} | ||
}; | ||
function processRequest(req, res) { | ||
@@ -25,0 +33,0 @@ try { |
@@ -14,3 +14,5 @@ var | ||
evt.locals.reason = "shutdown"; | ||
var workersToKill = 0; | ||
var workers = evt.service.workers; | ||
@@ -25,28 +27,18 @@ var exiting = false; | ||
exiting = true; | ||
workersToKill++; | ||
var killer = null; | ||
if (timeout > 0) { // start timeout if specified | ||
killer = setTimeout(getKiller(worker), timeout); | ||
} | ||
worker.process.on("exit", function() { | ||
if (killer) { | ||
clearTimeout(killer); | ||
worker.process.on("exit", getExitHandler(evt, worker, timeout > 0 ? setTimeout(getKiller(worker), timeout) : null, function() { | ||
workersToKill--; | ||
if (workersToKill === 0) { | ||
// no workers remain | ||
if (evt.service.workers.length === 0) { | ||
evt.locals.reason = "kill"; | ||
console.log("All workers shutdown. Exiting..."); | ||
evt.service.stop(timeout, cb); | ||
} else { | ||
cb(null, "Worker shutdown"); // DONE | ||
} | ||
} | ||
var first_worker; | ||
for (first_worker in evt.service.workers) { | ||
break; | ||
} | ||
if (!first_worker) { | ||
evt.locals.reason = "kill"; | ||
console.log("All workers shutdown. Exiting..."); | ||
process.exit(0); // exit master | ||
cb(); // DONE | ||
} | ||
else if (pid) { // only one worker needed to exit | ||
cb(null, "Worker shutdown"); // DONE | ||
} | ||
}); | ||
if (worker.onWorkerStop === true) { | ||
})); | ||
if (worker.onWorkerStop === true) { // try the nice way first | ||
worker.send({ cservice: { cmd: "onWorkerStop" } }); | ||
@@ -59,13 +51,6 @@ } else { | ||
if (exiting === false) { | ||
var first_worker; | ||
for (first_worker in evt.service.workers) { | ||
break; | ||
} | ||
if (!first_worker) { | ||
if (evt.service.workers.length === 0) { | ||
evt.locals.reason = "kill"; | ||
console.log("All workers shutdown. Exiting..."); | ||
process.exit(0); // exit master | ||
cb(); | ||
evt.service.stop(timeout, cb); | ||
} else { | ||
@@ -93,1 +78,12 @@ cb("No workers were shutdown"); | ||
} | ||
function getExitHandler(evt, worker, killer, cb) { | ||
return function() { | ||
if (killer) { | ||
clearTimeout(killer); | ||
killer = null; | ||
} | ||
cb(); | ||
}; | ||
} |
{ | ||
"name": "cluster-service", | ||
"version": "0.2.2", | ||
"author": { "name": "Aaron Silvas", "email": "asilvas@godaddy.com" }, | ||
"version": "0.2.3", | ||
"author": { | ||
"name": "Aaron Silvas", | ||
"email": "asilvas@godaddy.com" | ||
}, | ||
"description": "Turns your single process code into a fault-resilient multi-process service with built-in REST & CLI support", | ||
"main": "./cluster-service.js", | ||
"scripts": { "test": "node ./test.js" }, | ||
"scripts": { | ||
"test": "mocha --reporter spec" | ||
}, | ||
"dependencies": { | ||
"async": ">=0.2.x", | ||
"request": ">=2.21.0", | ||
"extend": ">=1.1.x" | ||
"async": ">=0.2.x", | ||
"request": ">=2.21.0", | ||
"extend": ">=1.1.x" | ||
}, | ||
"devDependencies": { | ||
"nodeunit": ">=0.8.1" | ||
"mocha": "~1.12.0", | ||
"istanbul": "~0.1.43" | ||
}, | ||
"repository": { | ||
"type" : "git", | ||
"url" : "https://github.com/godaddy/node-cluster-service.git" | ||
"type": "git", | ||
"url": "https://github.com/godaddy/node-cluster-service.git" | ||
}, | ||
"license": "MIT", | ||
"homepage": "https://github.com/godaddy/node-cluster-service", | ||
"bugs": { "url": "https://github.com/godaddy/node-cluster-service/issues" }, | ||
"keywords": [ "cluster", "service", "ha", "high availability", "cli", "remote access" ] | ||
"bugs": { | ||
"url": "https://github.com/godaddy/node-cluster-service/issues" | ||
}, | ||
"keywords": [ | ||
"cluster", | ||
"service", | ||
"ha", | ||
"high availability", | ||
"cli", | ||
"remote access" | ||
] | ||
} |
# cluster-service | ||
[![Build Status](https://travis-ci.org/godaddy/node-cluster-service.png)](https://travis-ci.org/godaddy/node-cluster-service) | ||
@@ -112,4 +113,11 @@ | ||
node test | ||
Windows: | ||
npm install mocha -g | ||
npm test | ||
Everyone else: | ||
npm test | ||
or individual tests... | ||
@@ -119,4 +127,11 @@ | ||
npm is wired up as well. | ||
npm test | ||
## Code Coverage | ||
Run: | ||
node_modules\.bin\istanbul cover node_modules\mocha\bin\_mocha -- -u exports -R spec | ||
Now you can view the coverage here: | ||
coverage/lcov-report/index.html |
41794
25
1098
136
2