2015-11-17 08:18:56 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
module.exports.create = function (opts) {
|
|
|
|
var id = '0';
|
2015-11-21 12:36:22 +00:00
|
|
|
var promiseApp;
|
2015-11-17 08:18:56 +00:00
|
|
|
|
2015-11-21 12:36:22 +00:00
|
|
|
function createAndBindInsecure(message, cb) {
|
|
|
|
// TODO conditional if 80 is being served by caddy
|
|
|
|
require('../lib/insecure-server').create(message.conf.externalPort, message.conf.insecurePort, message, function (err, webserver) {
|
|
|
|
console.info("#" + id + " Listening on http://" + webserver.address().address + ":" + webserver.address().port, '\n');
|
2015-11-17 08:18:56 +00:00
|
|
|
|
2015-11-21 12:36:22 +00:00
|
|
|
// we are returning the promise result to the caller
|
|
|
|
return cb(null, webserver, null, message);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function createAndBindServers(message, cb) {
|
|
|
|
// NOTE that message.conf[x] will be overwritten when the next message comes in
|
|
|
|
require('../lib/local-server').create(message.conf.certPaths, message.conf.localPort, message, function (err, webserver) {
|
2015-11-17 08:18:56 +00:00
|
|
|
if (err) {
|
|
|
|
console.error('[ERROR] worker.js');
|
|
|
|
console.error(err.stack);
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
|
2015-11-21 12:36:22 +00:00
|
|
|
console.info("#" + id + " Listening on " + message.conf.protocol + "://" + webserver.address().address + ":" + webserver.address().port, '\n');
|
2015-11-17 08:18:56 +00:00
|
|
|
|
2015-11-21 12:36:22 +00:00
|
|
|
// we don't need time to pass, just to be able to return
|
|
|
|
process.nextTick(function () {
|
|
|
|
createAndBindInsecure(message, cb);
|
|
|
|
});
|
2015-11-17 08:18:56 +00:00
|
|
|
|
2015-11-21 12:36:22 +00:00
|
|
|
// we are returning the promise result to the caller
|
|
|
|
return cb(null, null, webserver, message);
|
|
|
|
});
|
2015-11-17 08:18:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Worker Mode
|
|
|
|
//
|
|
|
|
function waitForConfig(message) {
|
2015-11-28 05:57:07 +00:00
|
|
|
if ('walnut.init' !== message.type) {
|
2015-11-17 08:18:56 +00:00
|
|
|
console.warn('[Worker] 0 got unexpected message:');
|
|
|
|
console.warn(message);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
process.removeListener('message', waitForConfig);
|
|
|
|
|
|
|
|
// NOTE: this callback must return a promise for an express app
|
2015-11-21 12:36:22 +00:00
|
|
|
createAndBindServers(message, function (err, insecserver, webserver, oldMessage) {
|
|
|
|
// TODO deep merge new message into old message
|
|
|
|
Object.keys(message.conf).forEach(function (key) {
|
|
|
|
oldMessage.conf[key] = message.conf[key];
|
|
|
|
});
|
2015-11-17 08:18:56 +00:00
|
|
|
var PromiseA = require('bluebird');
|
2015-11-21 12:36:22 +00:00
|
|
|
if (promiseApp) {
|
|
|
|
return promiseApp;
|
|
|
|
}
|
|
|
|
promiseApp = new PromiseA(function (resolve) {
|
2015-11-17 08:18:56 +00:00
|
|
|
function initWebServer(srvmsg) {
|
2015-11-28 05:57:07 +00:00
|
|
|
if ('walnut.webserver.onrequest' !== srvmsg.type) {
|
2015-11-17 08:18:56 +00:00
|
|
|
console.warn('[Worker] 1 got unexpected message:');
|
|
|
|
console.warn(srvmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
process.removeListener('message', initWebServer);
|
|
|
|
|
|
|
|
resolve(require('../lib/worker').create(webserver, srvmsg));
|
|
|
|
}
|
|
|
|
|
2015-11-28 05:57:07 +00:00
|
|
|
process.send({ type: 'walnut.webserver.listening' });
|
2015-11-17 08:18:56 +00:00
|
|
|
process.on('message', initWebServer);
|
|
|
|
}).then(function (app) {
|
|
|
|
console.info('[Worker Ready]');
|
|
|
|
return app;
|
|
|
|
});
|
2015-11-21 12:36:22 +00:00
|
|
|
return promiseApp;
|
2015-11-17 08:18:56 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Standalone Mode
|
|
|
|
//
|
|
|
|
if (opts) {
|
|
|
|
// NOTE: this callback must return a promise for an express app
|
2015-11-21 12:36:22 +00:00
|
|
|
createAndBindServers(opts, function (err, insecserver, webserver/*, message*/) {
|
2015-11-17 08:18:56 +00:00
|
|
|
var PromiseA = require('bluebird');
|
2015-11-21 12:36:22 +00:00
|
|
|
if (promiseApp) {
|
|
|
|
return promiseApp;
|
|
|
|
}
|
|
|
|
promiseApp = new PromiseA(function (resolve) {
|
2015-11-17 08:18:56 +00:00
|
|
|
opts.getConfig(function (srvmsg) {
|
|
|
|
resolve(require('../lib/worker').create(webserver, srvmsg));
|
|
|
|
});
|
|
|
|
}).then(function (app) {
|
|
|
|
console.info('[Standalone Ready]');
|
|
|
|
return app;
|
|
|
|
});
|
2015-11-21 12:36:22 +00:00
|
|
|
return promiseApp;
|
2015-11-17 08:18:56 +00:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// we are in cluster mode, as opposed to standalone mode
|
|
|
|
id = require('cluster').worker.id.toString();
|
|
|
|
// We have to wait to get the configuration from the master process
|
|
|
|
// before we can start our webserver
|
|
|
|
console.info('[Worker #' + id + '] online!');
|
|
|
|
process.on('message', waitForConfig);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Debugging
|
|
|
|
//
|
|
|
|
process.on('exit', function (code) {
|
|
|
|
// only sync code can run here
|
|
|
|
console.info('uptime:', process.uptime());
|
|
|
|
console.info(process.memoryUsage());
|
|
|
|
console.info('[exit] process.exit() has been called (or master has killed us).');
|
|
|
|
console.info(code);
|
|
|
|
});
|
|
|
|
process.on('beforeExit', function () {
|
|
|
|
// async can be scheduled here
|
|
|
|
console.info('[beforeExit] Event Loop is empty. Process will end.');
|
|
|
|
});
|
|
|
|
process.on('unhandledRejection', function (err) {
|
|
|
|
// this should always throw
|
|
|
|
// (it means somewhere we're not using bluebird by accident)
|
|
|
|
console.error('[caught] [unhandledRejection]');
|
|
|
|
console.error(Object.keys(err));
|
|
|
|
console.error(err);
|
|
|
|
console.error(err.stack);
|
|
|
|
});
|
|
|
|
process.on('rejectionHandled', function (msg) {
|
|
|
|
console.error('[rejectionHandled]');
|
|
|
|
console.error(msg);
|
|
|
|
});
|
|
|
|
};
|