plex-web-downloader/node_modules/cluster/lib/plugins/repl.js

196 lines
4.5 KiB
JavaScript

/*!
* Cluster - repl
* Copyright (c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var net = require('net')
, repl = require('repl');
/**
* Enable REPL with all arguments passed to `net.Server#listen()`.
*
* Examples:
*
* cluster(server)
* .use(cluster.stats())
* .use(cluster.repl('/var/run/cluster'))
* .listen();
*
* In the terminal:
*
* $ sudo telnet /var/run/cluster
*
* @return {Function}
* @api public
*/
exports = module.exports = function(){
var args = arguments;
if (!args.length) throw new Error('repl() plugin requires port/host or path');
return function(master){
var server
, sockets = [];
// start repl
function start(){
// TCP or unix-domain socket repl
server = net.createServer(function(sock){
sockets.push(sock);
var ctx = repl.start('cluster> ', sock).context;
master.emit('repl socket', sock);
// augment socket to provide some formatting methods
sock.title = function(str){ this.write('\n \033[36m' + str + '\033[0m\n'); }
sock.row = function(key, val){ this.write(' \033[90m' + key + ':\033[0m ' + val + '\n'); }
// merge commands into context
// executing in context of master
Object.keys(exports).forEach(function(cmd){
ctx[cmd] = function(){
var args = Array.prototype.slice.call(arguments);
args.unshift(master, sock);
return exports[cmd].apply(master, args);
};
});
});
// Apply all arguments given
server.listen.apply(server, args);
}
// initial master starts immediately
// replacements starts when the previous
// has closed
master.on(master.isChild
? 'restart'
: 'start', start);
// restart notification
master.on('restarting', function(){
sockets.forEach(function(sock){
if (sock.fd) {
sock.write('\n\033[33mrestarting\033[0m - closing connection soon\n');
}
});
});
// close
master.on('close', function(){
sockets.forEach(function(sock){
sock.fd && sock.end();
});
if (server && server.fd) server.close();
});
}
};
/**
* Define function `name`, with the given callback
* `fn(master, sock, ...)` and `description`.
*
* @param {String} name
* @param {Function} fn
* @param {String} desc
* @return {Object} exports for chaining
* @api public
*/
var define = exports.define = function(name, fn, desc){
(exports[name] = fn).description = desc;
return exports;
};
/**
* Display commmand help.
*/
define('help', function(master, sock){
sock.title('Commands');
Object.keys(exports).forEach(function(cmd){
if ('define' == cmd) return;
var fn = exports[cmd]
, params = fn.toString().match(/^function +\((.*?)\)/)[1]
, params = params.split(/ *, */).slice(2);
sock.row(
cmd + '(' + params.join(', ') + ')'
, fn.description);
});
sock.write('\n');
}, 'Display help information');
/**
* Spawn `n` additional workers with the given `signal`.
*/
define('spawn', function(master, sock, n, signal){
n = n || 1;
if (n < 0) {
n = Math.abs(n);
sock.write('removing ' + n + ' worker' + (n > 1 ? 's' : '')
+ ' with ' + (signal || 'SIGQUIT') + '\n');
master.remove(n, signal);
} else {
sock.write('spawning ' + n + ' worker' + (n > 1 ? 's' : '') + '\n');
master.spawn(n);
}
}, 'Spawn one or more additional workers, or remove one or more');
/**
* Output process ids.
*/
define('pids', function(master, sock){
sock.title('pids');
sock.row('master', process.pid);
master.children.forEach(function(worker){
sock.row('worker #' + worker.id, worker.proc.pid);
});
sock.write('\n');
}, 'Output process ids');
/**
* Kill the given worker by `id` and `signal`.
*/
define('kill', function(master, sock, id, signal){
var worker = master.children[id];
if (worker) {
worker.proc.kill(signal);
sock.write('sent \033[36m' + (signal || 'SIGTERM') + '\033[0m to worker #' + id + '\n');
} else {
sock.write('invalid worker id\n');
}
}, 'Send signal or SIGTERM to the given worker');
/**
* Gracefully shutdown.
*/
define('shutdown', function(master, sock){
master.close();
}, 'Gracefully shutdown server');
/**
* Hard shutdown.
*/
define('stop', function(master, sock){
master.destroy();
}, 'Hard shutdown');
/**
* Gracefully restart all workers.
*/
define('restart', function(master, sock){
master.restart();
}, 'Gracefully restart all workers');