mixdown-server
Advanced tools
Comparing version 1.0.3 to 1.0.5
176
index.js
var _ = require('lodash'); | ||
var opt = require('optimist') | ||
var util = require('util'); | ||
var cluster = require('cluster'); | ||
var mixdownServer = require('./lib/server.js'); | ||
var mixdownMaster = require('./lib/master.js'); | ||
var mixdownWorker = require('./lib/worker.js'); | ||
var path = require('path'); | ||
@@ -10,25 +10,4 @@ var packageJSON = require(path.join(process.cwd(), '/package.json')); | ||
// Export the factory | ||
exports.create = function(mixdown, options) { | ||
module.exports.create = function(mixdown, options) { | ||
var main = new Main(mixdown, options); | ||
// placeholder for options for starting the server | ||
var argv = opt | ||
.alias('h', 'help') | ||
.alias('?', 'help') | ||
.describe('help', 'Display help') | ||
.usage('Starts ' + packageJSON.name + ' framework for serving multiple sites.\n\nVersion: ' + packageJSON.version + '\nAuthor: ' + packageJSON.author) | ||
.alias('v', 'version') | ||
.describe('version', 'Display Mixdown application version.') | ||
.argv; | ||
if(argv.help) { | ||
opt.showHelp(); | ||
process.exit(); | ||
} | ||
if(argv.version) { | ||
console.log(packageJSON.version); | ||
process.exit(); | ||
} | ||
return main; | ||
@@ -38,13 +17,49 @@ }; | ||
var Main = function(mixdown, options) { | ||
// instance attrs | ||
this.server = null; | ||
this.workers = {}; | ||
this.workers = {}; // if this is a master, then we'll load this with child processes. | ||
this.socket = null; | ||
this.master = null; // if this is a master, then we'll set this delegate. | ||
this.worker = null; // if this is a worker, then we'll set this delegate. | ||
// passed configs. | ||
this.mixdown = mixdown; | ||
this.options = options; | ||
this.options = _.defaults(options || {}, { | ||
cluster: { | ||
on: false | ||
} | ||
}); | ||
}; | ||
var logServerInfo = function(server,message) { | ||
var hmap = _.map(server.mixdown.apps, function(app){ | ||
return _.pick(app, 'vhosts', 'id'); | ||
}); | ||
logger.info(message || 'Server Information. ', server.server.address(), hmap); | ||
}; | ||
Main.prototype.createMaster = function(callback) { | ||
var self = this; | ||
// start server. Sets up server, port, and starts the app. | ||
self.master = new mixdownMaster(self.workers, self.options, self.mixdown); | ||
self.master.start(function(err, data) { | ||
if (err) { | ||
logger.error("Could not start server. Stopping process.", err); | ||
process.exit(); | ||
} | ||
else { | ||
self.socket = data.socket; | ||
self.server = data.server; | ||
logServerInfo(self, 'Server started successfully.'); | ||
typeof(callback) === 'function' ? callback(err, self) : null; | ||
} | ||
}); | ||
}; | ||
Main.prototype.stop = function(callback) { | ||
@@ -55,46 +70,35 @@ throw new Error('stop() not implemented on server. TODO.'); | ||
Main.prototype.start = function(callback) { | ||
var that = this; | ||
var self = this; | ||
var mixdown = this.mixdown; | ||
var logServerInfo = function(message) { | ||
var hmap = _.map(mixdown.apps, function(app) { return _.pick(app, 'vhosts', 'id'); }); | ||
logger.info(message || 'Server Information. ', that.socket.address(), hmap); | ||
}; | ||
// this reload listener just logs the reload info. | ||
mixdown.on('reload', logServerInfo.bind(null, 'Mixdown reloaded. ')); | ||
mixdown.on('reload', function() { | ||
logServerInfo(self, 'Mixdown reloaded. '); | ||
}); | ||
var createServer = function(done) { | ||
// start server. Sets up server, port, and starts the app. | ||
that.server = new mixdownServer(that.mixdown, that.options); | ||
that.server.start(function(err, data) { | ||
if (err) { | ||
logger.critical("Could not start server. Stopping process.", err); | ||
process.exit(); | ||
} | ||
else { | ||
that.socket = data.socket; | ||
logServerInfo('Server started successfully.'); | ||
done(err, that); | ||
} | ||
}); | ||
}; | ||
// Start cluster. | ||
var children = this.workers; | ||
var clusterConfig = mixdown.main.options.cluster || {}; | ||
if(clusterConfig.on){ | ||
logger.info("Using cluster"); | ||
var numCPUs = clusterConfig.workers || require('os').cpus().length; | ||
var numChidrenToSpawn = clusterConfig.workers || require('os').cpus().length; | ||
if(cluster.isMaster){ | ||
logger.info("Starting master with " + numCPUs + " CPUs"); | ||
logger.info("Using cluster"); | ||
//cluser is on, and this is the master! | ||
logger.info("Starting master with " + numChidrenToSpawn + " workers"); | ||
// spawn n workers | ||
for (var i = 0; i < numCPUs; i++) { | ||
var child = cluster.fork(); | ||
children[child.process.pid] = child; | ||
for (var i = 0; i < numChidrenToSpawn; i++) { | ||
(function(){ | ||
var child = cluster.fork(); | ||
child.once('message',function(message){ | ||
if(message == 'ready'){ | ||
self.workers[child.process.pid] = child; | ||
logger.debug('initial child ready'); | ||
} | ||
}); | ||
})(); | ||
} | ||
@@ -108,9 +112,9 @@ | ||
_.each(children, function(child) { | ||
_.each(cluster.workers, function(child) { | ||
child.destroy(); // send suicide signal | ||
}); | ||
// create function to check that all workers are dead. | ||
// create function to check self all workers are dead. | ||
var checkExit = function() { | ||
if (_.keys(children).length == 0) { | ||
if (_.keys(cluster.workers).length == 0) { | ||
process.exit(); | ||
@@ -125,34 +129,50 @@ } | ||
setImmediate(checkExit); | ||
}); | ||
}); | ||
cluster.on('disconnect',function(worker) { | ||
delete self.workers[worker.process.pid]; | ||
logger.info('worker '+worker.process.pid+' disconnected'); | ||
}); | ||
cluster.on('exit', function(worker) { | ||
logger.error('Worker exited unexpectedly. Spawning new worker', worker); | ||
// remove the child from the tracked running list.. | ||
delete children[worker.process.pid]; | ||
delete self.workers[worker.process.pid]; | ||
// if it purposely destroyed itself, then do no re-spawn. | ||
// Otherwise, it was killed for some external reason and should create a new child in the pool. | ||
if (!worker.suicide) { | ||
// if it purposely destroyed itself, then do no re-spawn. | ||
if(!worker.suicide){ | ||
logger.error('Worker exited unexpectedly. Spawning new worker'); | ||
// spawn new child | ||
var child = cluster.fork(); | ||
children[child.process.pid] = child; | ||
child.on('message',function(message){ | ||
if(message == 'ready'){ | ||
logger.debug('respawned child ready id: ' + child.process.pid); | ||
self.workers[child.process.pid] = child; | ||
} | ||
}); | ||
} | ||
}); | ||
} else { | ||
logger.info("Worker ID", process.env.NODE_WORKER_ID); | ||
createServer(callback); | ||
self.createMaster(callback); | ||
} | ||
else { | ||
//cluser is on, and this is a worker! | ||
logger.info("new worker Worker id: "+process.pid); | ||
try { | ||
self.worker = new mixdownWorker(mixdown); | ||
} | ||
catch(e) { | ||
typeof(callback) === 'function' ? callback(e, self) : null; | ||
} | ||
} | ||
} | ||
} | ||
else { | ||
createServer(callback); | ||
//cluster isn't running so create a master server. | ||
self.createMaster(callback); | ||
} | ||
}; | ||
{ | ||
"name": "mixdown-server", | ||
"version": "1.0.3", | ||
"version": "1.0.5", | ||
"main": "index", | ||
@@ -5,0 +5,0 @@ "description": "Simple server for activiting a site.", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
12277
7
350
6
3