mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-07-01 00:27:50 +02:00
Merge remote-tracking branch 'origin/cluster' into cluster
Conflicts: loader.js
This commit is contained in:
13
app.js
13
app.js
@@ -28,6 +28,7 @@ var fs = require('fs'),
|
||||
semver = require('semver'),
|
||||
winston = require('winston'),
|
||||
path = require('path'),
|
||||
cluster = require('cluster'),
|
||||
pkg = require('./package.json'),
|
||||
utils = require('./public/src/utils.js');
|
||||
|
||||
@@ -157,6 +158,18 @@ function start() {
|
||||
process.on('SIGTERM', shutdown);
|
||||
process.on('SIGINT', shutdown);
|
||||
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) {
|
||||
winston.error(err.message);
|
||||
console.log(err.stack);
|
||||
|
||||
60
loader.js
60
loader.js
@@ -95,7 +95,8 @@ var nconf = require('nconf'),
|
||||
// nbb, nbbOld;
|
||||
|
||||
var Loader = {
|
||||
timesStarted: 0
|
||||
timesStarted: 0,
|
||||
shutdown_queue: []
|
||||
};
|
||||
|
||||
Loader.init = function() {
|
||||
@@ -106,11 +107,6 @@ Loader.init = function() {
|
||||
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) {
|
||||
worker.on('message', function(message) {
|
||||
if (message && typeof message === 'object' && message.action) {
|
||||
@@ -118,6 +114,12 @@ Loader.init = function() {
|
||||
case 'ready':
|
||||
console.log('[cluster] Child Process (' + worker.process.pid + ') listening for connections.');
|
||||
worker.send('bind');
|
||||
|
||||
// Kill an instance in the shutdown queue
|
||||
var workerToKill = Loader.shutdown_queue.pop();
|
||||
if (workerToKill) {
|
||||
cluster.workers[workerToKill].kill();
|
||||
}
|
||||
break;
|
||||
case 'restart':
|
||||
console.log('[cluster] Restarting...');
|
||||
@@ -125,6 +127,23 @@ Loader.init = function() {
|
||||
console.log('[cluster] Restarting...');
|
||||
});
|
||||
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:disconnect':
|
||||
notifyWorkers(worker, message);
|
||||
@@ -157,18 +176,37 @@ Loader.init = function() {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Loader.start();
|
||||
// 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) {
|
||||
async.eachSeries(Object.keys(cluster.workers), function(id, next) {
|
||||
cluster.workers[id].kill();
|
||||
next();
|
||||
}, callback);
|
||||
// Slate existing workers for termination -- welcome to death row.
|
||||
Loader.shutdown_queue = Loader.shutdown_queue.concat(Object.keys(cluster.workers));
|
||||
Loader.start();
|
||||
};
|
||||
|
||||
Loader.reload = function() {
|
||||
Object.keys(cluster.workers).forEach(function(worker_id) {
|
||||
cluster.workers[worker_id].send({
|
||||
action: 'reload'
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Loader.init();
|
||||
|
||||
@@ -40,7 +40,7 @@ var async = require('async'),
|
||||
emitter.emit('nodebb:ready');
|
||||
}
|
||||
|
||||
callback.apply(null, arguments);
|
||||
if (callback) callback.apply(null, arguments);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
134
src/meta/js.js
134
src/meta/js.js
@@ -7,6 +7,7 @@ var winston = require('winston'),
|
||||
_ = require('underscore'),
|
||||
os = require('os'),
|
||||
nconf = require('nconf'),
|
||||
cluster = require('cluster'),
|
||||
|
||||
plugins = require('../plugins'),
|
||||
emitter = require('../emitter'),
|
||||
@@ -120,70 +121,85 @@ module.exports = function(Meta) {
|
||||
};
|
||||
|
||||
Meta.js.minify = function(minify, callback) {
|
||||
var minifier = Meta.js.minifierProc = fork('minifier.js', {
|
||||
silent: true
|
||||
}),
|
||||
minifiedStream = minifier.stdio[1],
|
||||
minifiedString = '',
|
||||
mapStream = minifier.stdio[2],
|
||||
mapString = '',
|
||||
step = 0,
|
||||
onComplete = function() {
|
||||
if (step === 0) {
|
||||
return step++;
|
||||
}
|
||||
if (!cluster.isWorker || process.env.cluster_setup === 'true') {
|
||||
var minifier = Meta.js.minifierProc = fork('minifier.js', {
|
||||
silent: true
|
||||
}),
|
||||
minifiedStream = minifier.stdio[1],
|
||||
minifiedString = '',
|
||||
mapStream = minifier.stdio[2],
|
||||
mapString = '',
|
||||
step = 0,
|
||||
onComplete = function() {
|
||||
if (step === 0) {
|
||||
return step++;
|
||||
}
|
||||
|
||||
Meta.js.cache = minifiedString;
|
||||
Meta.js.map = mapString;
|
||||
winston.info('[meta/js] Compilation complete');
|
||||
emitter.emit('meta:js.compiled');
|
||||
minifier.kill();
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
Meta.js.cache = minifiedString;
|
||||
Meta.js.map = mapString;
|
||||
winston.info('[meta/js] Compilation complete');
|
||||
emitter.emit('meta:js.compiled');
|
||||
minifier.kill();
|
||||
|
||||
minifiedStream.on('data', function(buffer) {
|
||||
minifiedString += buffer.toString();
|
||||
});
|
||||
mapStream.on('data', function(buffer) {
|
||||
mapString += buffer.toString();
|
||||
});
|
||||
if (cluster.isWorker) {
|
||||
process.send({
|
||||
action: 'js-propagate',
|
||||
cache: minifiedString,
|
||||
map: mapString
|
||||
});
|
||||
}
|
||||
|
||||
minifier.on('message', function(message) {
|
||||
switch(message.type) {
|
||||
case 'end':
|
||||
if (message.payload === 'script') {
|
||||
winston.info('[meta/js] Successfully minified.');
|
||||
onComplete();
|
||||
} else if (message.payload === 'mapping') {
|
||||
winston.info('[meta/js] Retrieved Mapping.');
|
||||
onComplete();
|
||||
}
|
||||
break;
|
||||
case 'hash':
|
||||
Meta.js.hash = message.payload;
|
||||
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;
|
||||
}
|
||||
});
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
Meta.js.prepare(function() {
|
||||
minifier.send({
|
||||
action: 'js',
|
||||
relativePath: nconf.get('url') + '/',
|
||||
minify: minify,
|
||||
scripts: Meta.js.scripts.all
|
||||
minifiedStream.on('data', function(buffer) {
|
||||
minifiedString += buffer.toString();
|
||||
});
|
||||
});
|
||||
mapStream.on('data', function(buffer) {
|
||||
mapString += buffer.toString();
|
||||
});
|
||||
|
||||
minifier.on('message', function(message) {
|
||||
switch(message.type) {
|
||||
case 'end':
|
||||
if (message.payload === 'script') {
|
||||
winston.info('[meta/js] Successfully minified.');
|
||||
onComplete();
|
||||
} else if (message.payload === 'mapping') {
|
||||
winston.info('[meta/js] Retrieved Mapping.');
|
||||
onComplete();
|
||||
}
|
||||
break;
|
||||
case 'hash':
|
||||
Meta.js.hash = message.payload;
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
Meta.js.prepare(function() {
|
||||
minifier.send({
|
||||
action: 'js',
|
||||
relativePath: nconf.get('url') + '/',
|
||||
minify: minify,
|
||||
scripts: Meta.js.scripts.all
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Meta.js.killMinifier = function(callback) {
|
||||
|
||||
@@ -5,6 +5,7 @@ var mkdirp = require('mkdirp'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
nconf = require('nconf'),
|
||||
cluster = require('cluster'),
|
||||
|
||||
emitter = require('../emitter'),
|
||||
plugins = require('../plugins'),
|
||||
@@ -13,6 +14,16 @@ var mkdirp = require('mkdirp'),
|
||||
Templates = {};
|
||||
|
||||
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'),
|
||||
viewsPath = nconf.get('views_dir'),
|
||||
themeTemplatesPath = nconf.get('theme_templates_path');
|
||||
|
||||
@@ -128,14 +128,7 @@ module.exports = function(app, data) {
|
||||
|
||||
routeCurrentTheme(app, data.currentThemeId, data.themesData);
|
||||
routeThemeScreenshots(app, data.themesData);
|
||||
|
||||
if (process.env.cluster_setup === 'true') {
|
||||
meta.templates.compile();
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
emitter.emit('templates:compiled');
|
||||
}, 1000);
|
||||
}
|
||||
meta.templates.compile();
|
||||
|
||||
return middleware;
|
||||
};
|
||||
|
||||
@@ -56,10 +56,6 @@ module.exports = function(app, middleware, controllers) {
|
||||
});
|
||||
|
||||
router.get('/test', function(req, res) {
|
||||
var cluster = require('cluster');
|
||||
console.log('answered by worker', cluster.worker.id);
|
||||
res.send(200);
|
||||
process.exit();
|
||||
// res.redirect(404);
|
||||
res.redirect(404);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ var groups = require('../groups'),
|
||||
async = require('async'),
|
||||
winston = require('winston'),
|
||||
index = require('./index'),
|
||||
cluster = require('cluster'),
|
||||
|
||||
SocketAdmin = {
|
||||
user: require('./admin/user'),
|
||||
@@ -39,7 +40,13 @@ SocketAdmin.before = function(socket, method, next) {
|
||||
};
|
||||
|
||||
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) {
|
||||
|
||||
@@ -41,7 +41,7 @@ if(nconf.get('ssl')) {
|
||||
emailer.registerApp(app);
|
||||
notifications.init();
|
||||
|
||||
if (process.env.cluster_setup === 'true') {
|
||||
if (cluster.isWorker && process.env.cluster_setup === 'true') {
|
||||
user.startJobs();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ if(nconf.get('ssl')) {
|
||||
meta.js.minify(app.enabled('minification'));
|
||||
meta.css.minify();
|
||||
|
||||
if (process.env.cluster_setup === 'true') {
|
||||
if (cluster.isWorker && process.env.cluster_setup === 'true') {
|
||||
meta.sounds.init();
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user