wait for templates to compile even if using clustering
fix emitter.all
upgrade.check error first
removed plugins.ready, using callback on plugins.init
removed webserver.init, using webserver.listen
v1.18.x
barisusakli 10 years ago
parent 51212c2bfa
commit d946a2fcbd

@ -133,57 +133,16 @@ function start() {
winston.verbose('* using themes stored in: %s', nconf.get('themes_path')); winston.verbose('* using themes stored in: %s', nconf.get('themes_path'));
} }
var webserver = require('./src/webserver');
require('./src/database').init(function(err) {
if (err) {
winston.error(err.stack);
process.exit();
}
var meta = require('./src/meta');
meta.configs.init(function () {
var templates = require('templates.js'),
sockets = require('./src/socket.io'),
plugins = require('./src/plugins'),
upgrade = require('./src/upgrade');
templates.setGlobal('relative_path', nconf.get('relative_path'));
upgrade.check(function(schema_ok) {
if (schema_ok || nconf.get('check-schema') === false) {
webserver.init();
sockets.init(webserver.server);
if (nconf.get('isPrimary') === 'true' && !nconf.get('jobsDisabled')) {
require('./src/notifications').init();
require('./src/user').startJobs();
}
webserver.listen();
async.waterfall([
async.apply(meta.themes.setupPaths),
async.apply(plugins.ready),
async.apply(meta.templates.compile)
], function(err) {
if (err) {
winston.error(err.stack);
process.exit();
}
if (process.send) {
process.send({
action: 'ready'
});
}
});
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) { process.on('message', function(message) {
switch(message.action) { if (typeof message !== 'object') {
return;
}
var meta = require('./src/meta');
var emitter = require('./src/emitter');
switch (message.action) {
case 'reload': case 'reload':
meta.reload(); meta.reload();
break; break;
@ -191,14 +150,19 @@ function start() {
meta.js.cache = message.cache; meta.js.cache = message.cache;
meta.js.map = message.map; meta.js.map = message.map;
meta.js.hash = message.hash; meta.js.hash = message.hash;
emitter.emit('meta:js.compiled');
winston.verbose('[cluster] Client-side javascript and mapping propagated to worker %s', process.pid); winston.verbose('[cluster] Client-side javascript and mapping propagated to worker %s', process.pid);
break; break;
case 'css-propagate': case 'css-propagate':
meta.css.cache = message.cache; meta.css.cache = message.cache;
meta.css.acpCache = message.acpCache; meta.css.acpCache = message.acpCache;
meta.css.hash = message.hash; meta.css.hash = message.hash;
emitter.emit('meta:css.compiled');
winston.verbose('[cluster] Stylesheets propagated to worker %s', process.pid); winston.verbose('[cluster] Stylesheets propagated to worker %s', process.pid);
break; break;
case 'templates:compiled':
emitter.emit('templates:compiled');
break;
} }
}); });
@ -206,16 +170,42 @@ function start() {
winston.error(err.stack); winston.error(err.stack);
console.log(err.stack); console.log(err.stack);
meta.js.killMinifier(); require('./src/meta').js.killMinifier();
shutdown(1); shutdown(1);
}); });
} else {
async.waterfall([
function(next) {
require('./src/database').init(next);
},
function(next) {
require('./src/meta').configs.init(next);
},
function(next) {
require('./src/upgrade').check(next);
},
function(schema_ok, next) {
if (!schema_ok && nconf.get('check-schema') !== false) {
winston.warn('Your NodeBB schema is out-of-date. Please run the following command to bring your dataset up to spec:'); winston.warn('Your NodeBB schema is out-of-date. Please run the following command to bring your dataset up to spec:');
winston.warn(' ./nodebb upgrade'); winston.warn(' ./nodebb upgrade');
process.exit(); process.exit();
return;
}
var webserver = require('./src/webserver');
require('./src/socket.io').init(webserver.server);
if (nconf.get('isPrimary') === 'true' && !nconf.get('jobsDisabled')) {
require('./src/notifications').init();
require('./src/user').startJobs();
}
webserver.listen();
}
], function(err) {
if (err) {
winston.error(err.stack);
process.exit();
} }
});
});
}); });
} }
@ -243,7 +233,7 @@ function setup() {
winston.error('There was a problem completing NodeBB setup: ', err.message); winston.error('There was a problem completing NodeBB setup: ', err.message);
} else { } else {
if (data.hasOwnProperty('password')) { if (data.hasOwnProperty('password')) {
process.stdout.write('An administrative user was automatically created for you:\n') process.stdout.write('An administrative user was automatically created for you:\n');
process.stdout.write(' Username: ' + data.username + '\n'); process.stdout.write(' Username: ' + data.username + '\n');
process.stdout.write(' Password: ' + data.password + '\n'); process.stdout.write(' Password: ' + data.password + '\n');
process.stdout.write('\n'); process.stdout.write('\n');

@ -82,7 +82,7 @@ Loader.addWorkerEvents = function(worker) {
if (message && typeof message === 'object' && message.action) { if (message && typeof message === 'object' && message.action) {
switch (message.action) { switch (message.action) {
case 'ready': case 'ready':
if (Loader.js.cache) { if (Loader.js.cache && !worker.isPrimary) {
worker.send({ worker.send({
action: 'js-propagate', action: 'js-propagate',
cache: Loader.js.cache, cache: Loader.js.cache,
@ -91,7 +91,7 @@ Loader.addWorkerEvents = function(worker) {
}); });
} }
if (Loader.css.cache) { if (Loader.css.cache && !worker.isPrimary) {
worker.send({ worker.send({
action: 'css-propagate', action: 'css-propagate',
cache: Loader.css.cache, cache: Loader.css.cache,
@ -99,6 +99,8 @@ Loader.addWorkerEvents = function(worker) {
hash: Loader.css.hash hash: Loader.css.hash
}); });
} }
break; break;
case 'restart': case 'restart':
console.log('[cluster] Restarting...'); console.log('[cluster] Restarting...');
@ -132,6 +134,11 @@ Loader.addWorkerEvents = function(worker) {
hash: message.hash hash: message.hash
}, worker.pid); }, worker.pid);
break; break;
case 'templates:compiled':
Loader.notifyWorkers({
action: 'templates:compiled',
}, worker.pid);
break;
} }
} }
}); });

@ -6,39 +6,30 @@ var eventEmitter = new (require('events')).EventEmitter();
eventEmitter.all = function(events, callback) { eventEmitter.all = function(events, callback) {
var eventList = events.slice(0); var eventList = events.slice(0);
function onEvent(event) { events.forEach(function onEvent(event) {
eventEmitter.on(events[event], function() { eventEmitter.on(event, function() {
eventList.splice(eventList.indexOf(events[event]), 1); var index = eventList.indexOf(event);
if (index === -1) {
return;
}
eventList.splice(index, 1);
if (eventList.length === 0) { if (eventList.length === 0) {
callback(); callback();
} }
}); });
} });
for (var ev in events) {
if (events.hasOwnProperty(ev)) {
onEvent(ev);
}
}
}; };
eventEmitter.any = function(events, callback) { eventEmitter.any = function(events, callback) {
function onEvent(event) { events.forEach(function onEvent(event) {
eventEmitter.on(events[event], function() { eventEmitter.on(event, function() {
if (events !== null) { if (events !== null) {
callback(); callback();
} }
events = null; events = null;
}); });
} });
for (var ev in events) {
if (events.hasOwnProperty(ev)) {
onEvent(ev);
}
}
}; };
module.exports = eventEmitter; module.exports = eventEmitter;

@ -499,7 +499,10 @@ install.setup = function (callback) {
setCopyrightWidget, setCopyrightWidget,
function (next) { function (next) {
var upgrade = require('./upgrade'); var upgrade = require('./upgrade');
upgrade.check(function(uptodate) { upgrade.check(function(err, uptodate) {
if (err) {
return next(err);
}
if (!uptodate) { upgrade.upgrade(next); } if (!uptodate) { upgrade.upgrade(next); }
else { next(); } else { next(); }
}); });

@ -15,6 +15,7 @@ var mkdirp = require('mkdirp'),
Templates = {}; Templates = {};
Templates.compile = function(callback) { Templates.compile = function(callback) {
callback = callback || function() {};
var fromFile = nconf.get('from-file') || ''; var fromFile = nconf.get('from-file') || '';
if (nconf.get('isPrimary') === 'false' || fromFile.match('tpl')) { if (nconf.get('isPrimary') === 'false' || fromFile.match('tpl')) {
@ -22,11 +23,7 @@ Templates.compile = function(callback) {
winston.info('[minifier] Compiling templates skipped'); winston.info('[minifier] Compiling templates skipped');
} }
emitter.emit('templates:compiled'); return callback();
if (callback) {
callback();
}
return;
} }
var coreTemplatesPath = nconf.get('core_templates_path'), var coreTemplatesPath = nconf.get('core_templates_path'),
@ -119,15 +116,20 @@ Templates.compile = function(callback) {
}, function(err) { }, function(err) {
if (err) { if (err) {
winston.error('[meta/templates] ' + err.stack); winston.error('[meta/templates] ' + err.stack);
} else { return callback(err);
}
compileIndex(viewsPath, function() { compileIndex(viewsPath, function() {
winston.verbose('[meta/templates] Successfully compiled templates.'); winston.verbose('[meta/templates] Successfully compiled templates.');
emitter.emit('templates:compiled'); emitter.emit('templates:compiled');
if (callback) { if (process.send) {
callback(); process.send({
} action: 'templates:compiled'
}); });
} }
callback();
});
}); });
}); });
}); });

@ -39,9 +39,10 @@ var fs = require('fs'),
Plugins.libraryPaths.push(libraryPath); Plugins.libraryPaths.push(libraryPath);
}; };
Plugins.init = function(nbbApp, nbbMiddleware) { Plugins.init = function(nbbApp, nbbMiddleware, callback) {
callback = callback || function() {};
if (Plugins.initialized) { if (Plugins.initialized) {
return; return callback();
} }
app = nbbApp; app = nbbApp;
@ -55,7 +56,7 @@ var fs = require('fs'),
Plugins.reload(function(err) { Plugins.reload(function(err) {
if (err) { if (err) {
winston.error('[plugins] NodeBB encountered a problem while loading plugins', err.message); winston.error('[plugins] NodeBB encountered a problem while loading plugins', err.message);
return; return callback(err);
} }
if (global.env === 'development') { if (global.env === 'development') {
@ -64,6 +65,7 @@ var fs = require('fs'),
Plugins.initialized = true; Plugins.initialized = true;
emitter.emit('plugins:loaded'); emitter.emit('plugins:loaded');
callback();
}); });
Plugins.registerHook('core', { Plugins.registerHook('core', {
@ -72,14 +74,6 @@ var fs = require('fs'),
}); });
}; };
Plugins.ready = function(callback) {
if (!Plugins.initialized) {
emitter.once('plugins:loaded', callback);
} else {
callback();
}
};
Plugins.reload = function(callback) { Plugins.reload = function(callback) {
// Resetting all local plugin data // Resetting all local plugin data
Plugins.libraries = {}; Plugins.libraries = {};

@ -40,7 +40,6 @@
var router = express.Router(); var router = express.Router();
router.hotswapId = 'auth'; router.hotswapId = 'auth';
plugins.ready(function() {
loginStrategies.length = 0; loginStrategies.length = 0;
if (plugins.hasListeners('action:auth.overrideLogin')) { if (plugins.hasListeners('action:auth.overrideLogin')) {
@ -78,7 +77,6 @@
callback(); callback();
} }
}); });
});
}; };
Auth.login = function(req, username, password, next) { Auth.login = function(req, username, password, next) {

@ -25,18 +25,21 @@ var db = require('./database'),
Upgrade.check = function(callback) { Upgrade.check = function(callback) {
db.get('schemaDate', function(err, value) { db.get('schemaDate', function(err, value) {
if(!value) { if (err) {
return callback(err);
}
if (!value) {
db.set('schemaDate', latestSchema, function(err) { db.set('schemaDate', latestSchema, function(err) {
callback(true); if (err) {
return callback(err);
}
callback(null, true);
}); });
return; return;
} }
if (parseInt(value, 10) >= latestSchema) { callback(null, parseInt(value, 10) >= latestSchema);
callback(true);
} else {
callback(false);
}
}); });
}; };

@ -5,7 +5,7 @@ var path = require('path'),
fs = require('fs'), fs = require('fs'),
nconf = require('nconf'), nconf = require('nconf'),
express = require('express'), express = require('express'),
WebServer = express(), app = express(),
server, server,
winston = require('winston'), winston = require('winston'),
async = require('async'), async = require('async'),
@ -18,41 +18,64 @@ var path = require('path'),
routes = require('./routes'), routes = require('./routes'),
emitter = require('./emitter'), emitter = require('./emitter'),
helpers = require('./../public/src/modules/helpers'), helpers = require('../public/src/modules/helpers');
net;
if(nconf.get('ssl')) { if (nconf.get('ssl')) {
server = require('https').createServer({ server = require('https').createServer({
key: fs.readFileSync(nconf.get('ssl').key), key: fs.readFileSync(nconf.get('ssl').key),
cert: fs.readFileSync(nconf.get('ssl').cert) cert: fs.readFileSync(nconf.get('ssl').cert)
}, WebServer); }, app);
} else { } else {
server = require('http').createServer(WebServer); server = require('http').createServer(app);
} }
(function (app) { module.exports.server = server;
var port = nconf.get('port');
if (Array.isArray(port)) { server.on('error', function(err) {
if (!port.length) { winston.error(err);
winston.error('[startup] empty ports array in config.json'); if (err.code === 'EADDRINUSE') {
process.exit(); winston.error('NodeBB address in use, exiting...');
process.exit(0);
} else {
throw err;
} }
});
winston.warn('[startup] If you want to start nodebb on multiple ports please use loader.js'); if (server.setTimeout) {
winston.warn('[startup] Defaulting to first port in array, ' + port[0]); server.setTimeout(10000);
port = port[0]; }
if (!port) {
winston.error('[startup] Invalid port, exiting'); module.exports.listen = function() {
emailer.registerApp(app);
middleware = middleware(app);
helpers.register();
logger.init(app);
emitter.all(['templates:compiled', 'meta:js.compiled', 'meta:css.compiled'], function() {
winston.info('NodeBB Ready');
emitter.emit('nodebb:ready');
listen();
});
initializeNodeBB(function(err) {
if (err) {
winston.error(err);
process.exit(); process.exit();
} }
if (process.send) {
process.send({
action: 'ready'
});
} }
});
};
module.exports.init = function() { function initializeNodeBB(callback) {
var skipJS, skipLess, fromFile = nconf.get('from-file') || ''; var skipJS, skipLess, fromFile = nconf.get('from-file') || '';
emailer.registerApp(app);
if (fromFile.match('js')) { if (fromFile.match('js')) {
winston.info('[minifier] Minifying client-side JS skipped'); winston.info('[minifier] Minifying client-side JS skipped');
skipJS = true; skipJS = true;
@ -63,34 +86,38 @@ if(nconf.get('ssl')) {
skipLess = true; skipLess = true;
} }
// Preparation dependent on plugins async.waterfall([
plugins.ready(function() { async.apply(cacheStaticFiles),
async.apply(meta.themes.setupPaths),
function(next) {
plugins.init(app, middleware, next);
},
function(next) {
async.parallel([ async.parallel([
async.apply(meta.templates.compile),
async.apply(!skipJS ? meta.js.minify : meta.js.getFromFile, app.enabled('minification')), async.apply(!skipJS ? meta.js.minify : meta.js.getFromFile, app.enabled('minification')),
async.apply(!skipLess ? meta.css.minify : meta.css.getFromFile), async.apply(!skipLess ? meta.css.minify : meta.css.getFromFile),
async.apply(meta.sounds.init) async.apply(meta.sounds.init)
]); ], next);
},
function(results, next) {
plugins.fireHook('static:app.preload', { plugins.fireHook('static:app.preload', {
app: app, app: app,
middleware: middleware middleware: middleware
}, function(err) { }, next);
if (err) { },
return winston.error('[plugins] Encountered error while executing pre-router plugins hooks: ' + err.message); function(results, next) {
}
routes(app, middleware); routes(app, middleware);
}); next();
}); }
], callback);
middleware = middleware(app); }
plugins.init(app, middleware);
// Load server-side template helpers function cacheStaticFiles(callback) {
helpers.register(); if (global.env === 'development') {
return callback();
}
// Cache static files on production
if (global.env !== 'development') {
app.enable('cache'); app.enable('cache');
app.enable('minification'); app.enable('minification');
@ -100,12 +127,35 @@ if(nconf.get('ssl')) {
}, function(err, stdOut) { }, function(err, stdOut) {
if (!err) { if (!err) {
meta.config['cache-buster'] = stdOut.trim(); meta.config['cache-buster'] = stdOut.trim();
callback();
} else { } else {
fs.stat(path.join(__dirname, '../package.json'), function(err, stats) { fs.stat(path.join(__dirname, '../package.json'), function(err, stats) {
if (err) {
return callback(err);
}
meta.config['cache-buster'] = new Date(stats.mtime).getTime(); meta.config['cache-buster'] = new Date(stats.mtime).getTime();
callback();
}); });
} }
}); });
}
function listen(callback) {
var port = nconf.get('port');
if (Array.isArray(port)) {
if (!port.length) {
winston.error('[startup] empty ports array in config.json');
process.exit();
}
winston.warn('[startup] If you want to start nodebb on multiple ports please use loader.js');
winston.warn('[startup] Defaulting to first port in array, ' + port[0]);
port = port[0];
if (!port) {
winston.error('[startup] Invalid port, exiting');
process.exit();
}
} }
if (port !== 80 && port !== 443 && nconf.get('use_port') === false) { if (port !== 80 && port !== 443 && nconf.get('use_port') === false) {
@ -116,30 +166,6 @@ if(nconf.get('ssl')) {
if ((port === 80 || port === 443) && process.env.NODE_ENV !== 'development') { if ((port === 80 || port === 443) && process.env.NODE_ENV !== 'development') {
winston.info('Using ports 80 and 443 is not recommend; use a proxy instead. See README.md'); winston.info('Using ports 80 and 443 is not recommend; use a proxy instead. See README.md');
} }
};
server.on('error', function(err) {
winston.error(err.stack);
console.log(err.stack);
if (err.code === 'EADDRINUSE') {
winston.error('NodeBB address in use, exiting...');
process.exit(0);
} else {
throw err;
}
});
module.exports.server = server;
emitter.all(['templates:compiled', 'meta:js.compiled', 'meta:css.compiled'], function() {
winston.info('NodeBB Ready');
emitter.emit('nodebb:ready');
});
server.setTimout && server.setTimeout(10000);
module.exports.listen = function() {
logger.init(app);
var isSocket = isNaN(port), var isSocket = isNaN(port),
args = isSocket ? [port] : [port, nconf.get('bind_address')], args = isSocket ? [port] : [port, nconf.get('bind_address')],
@ -161,12 +187,9 @@ if(nconf.get('ssl')) {
// Alter umask if necessary // Alter umask if necessary
if (isSocket) { if (isSocket) {
oldUmask = process.umask('0000'); oldUmask = process.umask('0000');
net = require('net');
module.exports.testSocket(port, function(err) { module.exports.testSocket(port, function(err) {
if (!err) { if (!err) {
emitter.on('nodebb:ready', function() {
server.listen.apply(server, args); server.listen.apply(server, args);
});
} else { } else {
winston.error('[startup] NodeBB was unable to secure domain socket access (' + port + ')'); winston.error('[startup] NodeBB was unable to secure domain socket access (' + port + ')');
winston.error('[startup] ' + err.message); winston.error('[startup] ' + err.message);
@ -174,17 +197,15 @@ if(nconf.get('ssl')) {
} }
}); });
} else { } else {
emitter.on('nodebb:ready', function() {
server.listen.apply(server, args); server.listen.apply(server, args);
});
} }
}; }
module.exports.testSocket = function(socketPath, callback) { module.exports.testSocket = function(socketPath, callback) {
if (typeof socketPath !== 'string') { if (typeof socketPath !== 'string') {
return callback(new Error('invalid socket path : ' + socketPath)); return callback(new Error('invalid socket path : ' + socketPath));
} }
var net = require('net');
async.series([ async.series([
function(next) { function(next) {
fs.exists(socketPath, function(exists) { fs.exists(socketPath, function(exists) {
@ -207,6 +228,6 @@ if(nconf.get('ssl')) {
}, },
async.apply(fs.unlink, socketPath), // The socket was stale, kick it out of the way async.apply(fs.unlink, socketPath), // The socket was stale, kick it out of the way
], callback); ], callback);
}; };
}(WebServer));

Loading…
Cancel
Save