Merge remote-tracking branch 'origin/cluster' into cluster

Conflicts:
	loader.js
v1.18.x
barisusakli 11 years ago
commit 0b2df849bd

@ -28,6 +28,7 @@ var fs = require('fs'),
semver = require('semver'), semver = require('semver'),
winston = require('winston'), winston = require('winston'),
path = require('path'), path = require('path'),
cluster = require('cluster'),
pkg = require('./package.json'), pkg = require('./package.json'),
utils = require('./public/src/utils.js'); utils = require('./public/src/utils.js');
@ -157,6 +158,18 @@ function start() {
process.on('SIGTERM', shutdown); process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown); process.on('SIGINT', shutdown);
process.on('SIGHUP', restart); process.on('SIGHUP', restart);
process.on('message', function(message) {
switch(message.action) {
case 'reload':
meta.reload();
break;
case 'js-propagate':
meta.js.cache = message.cache;
meta.js.map = message.map;
winston.info('[cluster] Client-side javascript and mapping propagated to worker ' + cluster.worker.id);
break;
}
})
process.on('uncaughtException', function(err) { process.on('uncaughtException', function(err) {
winston.error(err.message); winston.error(err.message);
console.log(err.stack); console.log(err.stack);

@ -95,7 +95,8 @@ var nconf = require('nconf'),
// nbb, nbbOld; // nbb, nbbOld;
var Loader = { var Loader = {
timesStarted: 0 timesStarted: 0,
shutdown_queue: []
}; };
Loader.init = function() { Loader.init = function() {
@ -106,11 +107,6 @@ Loader.init = function() {
silent: process.env.NODE_ENV !== 'development' ? true : false silent: process.env.NODE_ENV !== 'development' ? true : false
}); });
for(var x=0;x<numCPUs;x++) {
// Only the first worker sets up templates/sounds/jobs/etc
cluster.fork({ cluster_setup: x === 0 });
}
cluster.on('fork', function(worker) { cluster.on('fork', function(worker) {
worker.on('message', function(message) { worker.on('message', function(message) {
if (message && typeof message === 'object' && message.action) { if (message && typeof message === 'object' && message.action) {
@ -118,6 +114,12 @@ Loader.init = function() {
case 'ready': case 'ready':
console.log('[cluster] Child Process (' + worker.process.pid + ') listening for connections.'); console.log('[cluster] Child Process (' + worker.process.pid + ') listening for connections.');
worker.send('bind'); worker.send('bind');
// Kill an instance in the shutdown queue
var workerToKill = Loader.shutdown_queue.pop();
if (workerToKill) {
cluster.workers[workerToKill].kill();
}
break; break;
case 'restart': case 'restart':
console.log('[cluster] Restarting...'); console.log('[cluster] Restarting...');
@ -125,6 +127,23 @@ Loader.init = function() {
console.log('[cluster] Restarting...'); console.log('[cluster] Restarting...');
}); });
break; break;
case 'reload':
console.log('[cluster] Reloading...');
Loader.reload();
break;
case 'js-propagate':
var otherWorkers = Object.keys(cluster.workers).filter(function(worker_id) {
return parseInt(worker_id, 10) !== parseInt(worker.id, 10);
});
otherWorkers.forEach(function(worker_id) {
cluster.workers[worker_id].send({
action: 'js-propagate',
cache: message.cache,
map: message.map
});
});
break;
case 'user:connect': case 'user:connect':
case 'user:disconnect': case 'user:disconnect':
notifyWorkers(worker, message); notifyWorkers(worker, message);
@ -157,18 +176,37 @@ Loader.init = function() {
} }
console.log('[cluster] Child Process (' + worker.process.pid + ') has exited (code: ' + code + ')'); console.log('[cluster] Child Process (' + worker.process.pid + ') has exited (code: ' + code + ')');
cluster.fork(); if (!worker.suicide) {
console.log('[cluster] Spinning up another process...')
cluster.fork();
}
}); });
process.on('SIGHUP', Loader.restart); process.on('SIGHUP', Loader.restart);
Loader.start();
// fs.writeFile(__dirname + '/pidfile', process.pid); // fs.writeFile(__dirname + '/pidfile', process.pid);
}; };
Loader.start = function() {
for(var x=0;x<numCPUs;x++) {
// Only the first worker sets up templates/sounds/jobs/etc
cluster.fork({ cluster_setup: x === 0 });
}
}
Loader.restart = function(callback) { Loader.restart = function(callback) {
async.eachSeries(Object.keys(cluster.workers), function(id, next) { // Slate existing workers for termination -- welcome to death row.
cluster.workers[id].kill(); Loader.shutdown_queue = Loader.shutdown_queue.concat(Object.keys(cluster.workers));
next(); Loader.start();
}, callback); };
Loader.reload = function() {
Object.keys(cluster.workers).forEach(function(worker_id) {
cluster.workers[worker_id].send({
action: 'reload'
});
});
}; };
Loader.init(); Loader.init();

@ -40,7 +40,7 @@ var async = require('async'),
emitter.emit('nodebb:ready'); emitter.emit('nodebb:ready');
} }
callback.apply(null, arguments); if (callback) callback.apply(null, arguments);
}); });
}); });
}; };

@ -7,6 +7,7 @@ var winston = require('winston'),
_ = require('underscore'), _ = require('underscore'),
os = require('os'), os = require('os'),
nconf = require('nconf'), nconf = require('nconf'),
cluster = require('cluster'),
plugins = require('../plugins'), plugins = require('../plugins'),
emitter = require('../emitter'), emitter = require('../emitter'),
@ -120,70 +121,85 @@ module.exports = function(Meta) {
}; };
Meta.js.minify = function(minify, callback) { Meta.js.minify = function(minify, callback) {
var minifier = Meta.js.minifierProc = fork('minifier.js', { if (!cluster.isWorker || process.env.cluster_setup === 'true') {
silent: true var minifier = Meta.js.minifierProc = fork('minifier.js', {
}), silent: true
minifiedStream = minifier.stdio[1], }),
minifiedString = '', minifiedStream = minifier.stdio[1],
mapStream = minifier.stdio[2], minifiedString = '',
mapString = '', mapStream = minifier.stdio[2],
step = 0, mapString = '',
onComplete = function() { step = 0,
if (step === 0) { onComplete = function() {
return step++; if (step === 0) {
} return step++;
}
Meta.js.cache = minifiedString; Meta.js.cache = minifiedString;
Meta.js.map = mapString; Meta.js.map = mapString;
winston.info('[meta/js] Compilation complete'); winston.info('[meta/js] Compilation complete');
emitter.emit('meta:js.compiled'); emitter.emit('meta:js.compiled');
minifier.kill(); minifier.kill();
if (typeof callback === 'function') {
callback(); if (cluster.isWorker) {
} process.send({
}; action: 'js-propagate',
cache: minifiedString,
map: mapString
});
}
minifiedStream.on('data', function(buffer) { if (typeof callback === 'function') {
minifiedString += buffer.toString(); callback();
}); }
mapStream.on('data', function(buffer) { };
mapString += buffer.toString();
});
minifier.on('message', function(message) { minifiedStream.on('data', function(buffer) {
switch(message.type) { minifiedString += buffer.toString();
case 'end': });
if (message.payload === 'script') { mapStream.on('data', function(buffer) {
winston.info('[meta/js] Successfully minified.'); mapString += buffer.toString();
onComplete(); });
} else if (message.payload === 'mapping') {
winston.info('[meta/js] Retrieved Mapping.'); minifier.on('message', function(message) {
onComplete(); switch(message.type) {
} case 'end':
break; if (message.payload === 'script') {
case 'hash': winston.info('[meta/js] Successfully minified.');
Meta.js.hash = message.payload; onComplete();
break; } else if (message.payload === 'mapping') {
case 'error': winston.info('[meta/js] Retrieved Mapping.');
winston.error('[meta/js] Could not compile client-side scripts! ' + message.payload.message); onComplete();
minifier.kill(); }
if (typeof callback === 'function') { break;
callback(new Error(message.payload.message)); case 'hash':
} else { Meta.js.hash = message.payload;
process.exit(0); break;
case 'error':
winston.error('[meta/js] Could not compile client-side scripts! ' + message.payload.message);
minifier.kill();
if (typeof callback === 'function') {
callback(new Error(message.payload.message));
} else {
process.exit(0);
}
break;
} }
break; });
}
});
Meta.js.prepare(function() { Meta.js.prepare(function() {
minifier.send({ minifier.send({
action: 'js', action: 'js',
relativePath: nconf.get('url') + '/', relativePath: nconf.get('url') + '/',
minify: minify, minify: minify,
scripts: Meta.js.scripts.all scripts: Meta.js.scripts.all
});
}); });
}); } else {
if (typeof callback === 'function') {
callback();
}
}
}; };
Meta.js.killMinifier = function(callback) { Meta.js.killMinifier = function(callback) {

@ -5,6 +5,7 @@ var mkdirp = require('mkdirp'),
path = require('path'), path = require('path'),
fs = require('fs'), fs = require('fs'),
nconf = require('nconf'), nconf = require('nconf'),
cluster = require('cluster'),
emitter = require('../emitter'), emitter = require('../emitter'),
plugins = require('../plugins'), plugins = require('../plugins'),
@ -13,6 +14,16 @@ var mkdirp = require('mkdirp'),
Templates = {}; Templates = {};
Templates.compile = function(callback) { Templates.compile = function(callback) {
if (cluster.isWorker && process.env.cluster_setup !== 'true') {
return setTimeout(function() {
console.log('FAKING TEMPLATE COMPILE');
emitter.emit('templates:compiled');
if (callback) callback();
}, 1000);
} else {
console.log('REAL TEMPLATE COMPILE');
}
var baseTemplatesPath = nconf.get('base_templates_path'), var baseTemplatesPath = nconf.get('base_templates_path'),
viewsPath = nconf.get('views_dir'), viewsPath = nconf.get('views_dir'),
themeTemplatesPath = nconf.get('theme_templates_path'); themeTemplatesPath = nconf.get('theme_templates_path');

@ -128,14 +128,7 @@ module.exports = function(app, data) {
routeCurrentTheme(app, data.currentThemeId, data.themesData); routeCurrentTheme(app, data.currentThemeId, data.themesData);
routeThemeScreenshots(app, data.themesData); routeThemeScreenshots(app, data.themesData);
meta.templates.compile();
if (process.env.cluster_setup === 'true') {
meta.templates.compile();
} else {
setTimeout(function() {
emitter.emit('templates:compiled');
}, 1000);
}
return middleware; return middleware;
}; };

@ -56,10 +56,6 @@ module.exports = function(app, middleware, controllers) {
}); });
router.get('/test', function(req, res) { router.get('/test', function(req, res) {
var cluster = require('cluster'); res.redirect(404);
console.log('answered by worker', cluster.worker.id);
res.send(200);
process.exit();
// res.redirect(404);
}); });
}; };

@ -14,6 +14,7 @@ var groups = require('../groups'),
async = require('async'), async = require('async'),
winston = require('winston'), winston = require('winston'),
index = require('./index'), index = require('./index'),
cluster = require('cluster'),
SocketAdmin = { SocketAdmin = {
user: require('./admin/user'), user: require('./admin/user'),
@ -39,7 +40,13 @@ SocketAdmin.before = function(socket, method, next) {
}; };
SocketAdmin.reload = function(socket, data, callback) { SocketAdmin.reload = function(socket, data, callback) {
meta.reload(callback); if (cluster.isWorker) {
process.send({
action: 'reload'
});
} else {
meta.reload(callback);
}
}; };
SocketAdmin.restart = function(socket, data, callback) { SocketAdmin.restart = function(socket, data, callback) {

@ -41,7 +41,7 @@ if(nconf.get('ssl')) {
emailer.registerApp(app); emailer.registerApp(app);
notifications.init(); notifications.init();
if (process.env.cluster_setup === 'true') { if (cluster.isWorker && process.env.cluster_setup === 'true') {
user.startJobs(); user.startJobs();
} }
@ -50,7 +50,7 @@ if(nconf.get('ssl')) {
meta.js.minify(app.enabled('minification')); meta.js.minify(app.enabled('minification'));
meta.css.minify(); meta.css.minify();
if (process.env.cluster_setup === 'true') { if (cluster.isWorker && process.env.cluster_setup === 'true') {
meta.sounds.init(); meta.sounds.init();
} }
}); });

Loading…
Cancel
Save