2015-11-04 09:22:00 +00:00
|
|
|
'use strict';
|
|
|
|
|
2015-11-06 11:05:32 +00:00
|
|
|
// TODO if RAM is very low we should not fork at all,
|
|
|
|
// but use a different process altogether
|
|
|
|
|
2015-11-17 08:18:56 +00:00
|
|
|
console.info('pid:', process.pid);
|
|
|
|
console.info('title:', process.title);
|
|
|
|
console.info('arch:', process.arch);
|
|
|
|
console.info('platform:', process.platform);
|
|
|
|
console.info('\n\n\n[MASTER] Welcome to WALNUT!');
|
2015-11-04 09:22:00 +00:00
|
|
|
|
|
|
|
var cluster = require('cluster');
|
|
|
|
var path = require('path');
|
2015-11-17 08:18:56 +00:00
|
|
|
//var minWorkers = 2;
|
2015-11-19 07:42:20 +00:00
|
|
|
var numCores = 2; // Math.max(minWorkers, require('os').cpus().length);
|
2015-11-06 11:05:32 +00:00
|
|
|
var workers = [];
|
|
|
|
var caddypath = '/usr/local/bin/caddy';
|
|
|
|
var useCaddy = require('fs').existsSync(caddypath);
|
|
|
|
var conf = {
|
2015-11-23 08:45:20 +00:00
|
|
|
localPort: process.argv[2] || (useCaddy ? 4080 : 443) // system / local network
|
|
|
|
, insecurePort: process.argv[3] || (useCaddy ? 80 : 80) // meh
|
2015-11-06 11:05:32 +00:00
|
|
|
, externalPort: 443 // world accessible
|
2015-11-23 08:45:20 +00:00
|
|
|
, externalPortInsecure: 80 // world accessible
|
2015-11-06 11:05:32 +00:00
|
|
|
// TODO externalInsecurePort?
|
|
|
|
, locked: false // TODO XXX
|
|
|
|
, ipcKey: null
|
2015-11-19 22:13:20 +00:00
|
|
|
, caddyfilepath: path.join(__dirname, '..', '..', 'Caddyfile')
|
|
|
|
, sitespath: path.join(__dirname, '..', '..', 'sites-enabled')
|
2015-11-06 11:05:32 +00:00
|
|
|
};
|
|
|
|
var state = {};
|
|
|
|
var caddy;
|
2015-11-04 09:22:00 +00:00
|
|
|
|
2015-11-06 11:05:32 +00:00
|
|
|
if (useCaddy) {
|
|
|
|
conf.caddypath = caddypath;
|
2015-11-06 01:00:22 +00:00
|
|
|
}
|
|
|
|
|
2015-11-06 11:05:32 +00:00
|
|
|
function fork() {
|
|
|
|
if (workers.length < numCores) {
|
|
|
|
workers.push(cluster.fork());
|
2015-11-04 09:22:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cluster.on('online', function (worker) {
|
2015-11-06 11:05:32 +00:00
|
|
|
var path = require('path');
|
|
|
|
// TODO XXX Should these be configurable? If so, where?
|
2015-11-21 12:36:22 +00:00
|
|
|
var certPaths = [path.join(__dirname, '..', '..', 'certs', 'live')];
|
2015-11-06 11:05:32 +00:00
|
|
|
var info;
|
2015-11-21 12:36:22 +00:00
|
|
|
var config = require('../../config');
|
2015-11-28 05:06:19 +00:00
|
|
|
conf.ddns = config.ddns;
|
|
|
|
conf.redirects = config.redirects;
|
2015-11-06 11:05:32 +00:00
|
|
|
|
2015-11-17 08:18:56 +00:00
|
|
|
console.info('[MASTER] Worker ' + worker.process.pid + ' is online');
|
2015-11-06 01:00:22 +00:00
|
|
|
fork();
|
|
|
|
|
2015-11-17 08:18:56 +00:00
|
|
|
// TODO communicate config with environment vars?
|
2015-11-06 11:05:32 +00:00
|
|
|
info = {
|
|
|
|
type: 'com.daplie.walnut.init'
|
|
|
|
, conf: {
|
|
|
|
protocol: useCaddy ? 'http' : 'https'
|
|
|
|
, externalPort: conf.externalPort
|
|
|
|
, localPort: conf.localPort
|
|
|
|
, insecurePort: conf.insecurePort
|
|
|
|
, trustProxy: useCaddy ? true : false
|
|
|
|
, certPaths: useCaddy ? null : certPaths
|
|
|
|
, ipcKey: null
|
2015-11-21 12:36:22 +00:00
|
|
|
// TODO let this load after server is listening
|
|
|
|
, redirects: config.redirects
|
2015-11-28 05:06:19 +00:00
|
|
|
, ddns: config.ddns
|
2015-11-06 11:05:32 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
worker.send(info);
|
|
|
|
|
|
|
|
function touchMaster(msg) {
|
|
|
|
if ('com.daplie.walnut.webserver.listening' !== msg.type) {
|
|
|
|
console.warn('[MASTER] received unexpected message from worker');
|
|
|
|
console.warn(msg);
|
|
|
|
return;
|
|
|
|
}
|
2015-11-04 09:22:00 +00:00
|
|
|
|
2015-11-06 11:05:32 +00:00
|
|
|
// calls init if init has not been called
|
|
|
|
state.caddy = caddy;
|
|
|
|
state.workers = workers;
|
2015-11-17 08:18:56 +00:00
|
|
|
require('../lib/master').touch(conf, state).then(function () {
|
2015-11-06 11:05:32 +00:00
|
|
|
info.type = 'com.daplie.walnut.webserver.onrequest';
|
|
|
|
info.conf.ipcKey = conf.ipcKey;
|
2015-11-12 11:14:59 +00:00
|
|
|
info.conf.memstoreSock = conf.memstoreSock;
|
|
|
|
info.conf.sqlite3Sock = conf.sqlite3Sock;
|
2015-11-18 11:44:22 +00:00
|
|
|
// TODO get this from db config instead
|
2015-11-19 22:13:20 +00:00
|
|
|
var config = require('../../config');
|
2015-11-18 11:44:22 +00:00
|
|
|
info.conf.primaryNameserver = config.primaryNameserver;
|
|
|
|
info.conf.nameservers = config.nameservers;
|
2015-11-19 12:34:59 +00:00
|
|
|
// TODO get this from db config instead
|
|
|
|
info.conf.privkey = config.privkey;
|
|
|
|
info.conf.pubkey = config.pubkey;
|
2015-11-21 12:36:22 +00:00
|
|
|
info.conf.redirects = config.redirects;
|
2015-11-28 05:06:19 +00:00
|
|
|
info.conf.ddns = config.ddns;
|
2015-11-06 11:05:32 +00:00
|
|
|
worker.send(info);
|
|
|
|
});
|
2015-11-04 09:22:00 +00:00
|
|
|
}
|
2015-11-06 11:05:32 +00:00
|
|
|
worker.on('message', touchMaster);
|
2015-11-04 09:22:00 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
cluster.on('exit', function (worker, code, signal) {
|
2015-11-17 08:18:56 +00:00
|
|
|
console.info('[MASTER] Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal);
|
2015-11-04 09:22:00 +00:00
|
|
|
|
2015-11-06 11:05:32 +00:00
|
|
|
workers = workers.map(function (w) {
|
|
|
|
if (worker !== w) {
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}).filter(function (w) {
|
|
|
|
return w;
|
2015-11-04 09:22:00 +00:00
|
|
|
});
|
|
|
|
|
2015-11-19 07:42:20 +00:00
|
|
|
//console.log('WARNING: worker spawning turned off for debugging ');
|
|
|
|
fork();
|
2015-11-04 09:22:00 +00:00
|
|
|
});
|
|
|
|
|
2015-11-06 11:05:32 +00:00
|
|
|
fork();
|
2015-11-04 09:22:00 +00:00
|
|
|
|
2015-11-06 11:05:32 +00:00
|
|
|
if (useCaddy) {
|
2015-11-17 08:18:56 +00:00
|
|
|
caddy = require('../lib/spawn-caddy').create(conf);
|
2015-11-06 11:05:32 +00:00
|
|
|
// relies on { localPort, locked }
|
|
|
|
caddy.spawn(conf);
|
2015-11-04 09:22:00 +00:00
|
|
|
}
|