walnut.js/boot/master.js

126 lines
3.4 KiB
JavaScript
Raw Normal View History

'use strict';
// TODO if RAM is very low we should not fork at all,
// but use a different process altogether
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!');
2016-03-31 16:30:04 +00:00
function tryConf(pathname, def) {
try {
return require(pathname);
} catch(e) {
return def;
}
}
2016-03-29 01:12:35 +00:00
var path = require('path');
var cluster = require('cluster');
//var minWorkers = 2;
2015-11-19 07:42:20 +00:00
var numCores = 2; // Math.max(minWorkers, require('os').cpus().length);
var workers = [];
2016-03-31 06:39:15 +00:00
var state = { firstRun: true };
2016-03-31 16:30:04 +00:00
// TODO Should these be configurable? If so, where?
// TODO communicate config with environment vars?
2016-04-09 23:14:00 +00:00
var walnut = tryConf(
path.join('..', '..', 'config.walnut')
, { externalPort: 443
, externalInsecurePort: 80
, certspath: path.join(__dirname, '..', '..', 'certs', 'live')
}
);
2016-03-31 16:30:04 +00:00
var caddy = tryConf(
2016-04-09 23:14:00 +00:00
path.join('..', '..', 'config.caddy')
, { conf: path.join(__dirname, '..', '..', 'Caddyfile')
2016-03-31 16:30:04 +00:00
, bin: null // '/usr/local/bin/caddy'
, sitespath: null // path.join(__dirname, 'sites-enabled')
, locked: false // true
}
);
2016-04-09 23:14:00 +00:00
var letsencrypt = tryConf(
path.join('..', '..', 'config.letsencrypt')
, { configDir: path.join(__dirname, '..', '..', 'letsencrypt')
, email: null
, agreeTos: false
}
);
var useCaddy = caddy.bin && require('fs').existsSync(caddy.bin);
2016-03-31 16:30:04 +00:00
var info = {
type: 'walnut.init'
, conf: {
protocol: useCaddy ? 'http' : 'https'
2016-04-09 23:14:00 +00:00
, externalPort: walnut.externalPort
, externalPortInsecure: walnut.externalInsecurePort // TODO externalInsecurePort
, localPort: walnut.localPort || (useCaddy ? 4080 : 443) // system / local network
, insecurePort: walnut.insecurePort || (useCaddy ? 80 : 80) // meh
2016-03-31 16:30:04 +00:00
, certPaths: useCaddy ? null : [
2016-04-09 23:14:00 +00:00
walnut.certspath
, path.join(letsencrypt.configDir, 'live')
2016-03-31 16:30:04 +00:00
]
, trustProxy: useCaddy ? true : false
2016-04-09 23:14:00 +00:00
, lexConf: letsencrypt
, varpath: path.join(__dirname, '..', '..', 'var')
, etcpath: path.join(__dirname, '..', '..', 'etc')
2016-03-31 16:30:04 +00:00
}
};
function fork() {
if (workers.length < numCores) {
workers.push(cluster.fork());
}
}
cluster.on('online', function (worker) {
console.info('[MASTER] Worker ' + worker.process.pid + ' is online');
fork();
2016-03-31 06:39:15 +00:00
if (state.firstRun) {
state.firstRun = false;
if (useCaddy) {
2016-03-31 16:30:04 +00:00
caddy = require('../lib/spawn-caddy').create(caddy);
2016-03-31 06:39:15 +00:00
// relies on { localPort, locked }
2016-03-31 16:30:04 +00:00
caddy.spawn(caddy);
2016-03-31 06:39:15 +00:00
}
2016-04-09 23:14:00 +00:00
// TODO dyndns in master?
2016-03-31 06:39:15 +00:00
}
function touchMaster(msg) {
2015-11-28 06:05:27 +00:00
if ('walnut.webserver.listening' !== msg.type) {
console.warn('[MASTER] received unexpected message from worker');
console.warn(msg);
return;
}
state.caddy = caddy;
state.workers = workers;
2016-04-09 23:14:00 +00:00
// calls init if init has not been called
require('../lib/master').touch(info.conf, state).then(function (newConf) {
worker.send({ type: 'walnut.webserver.onrequest', conf: newConf });
});
}
2016-03-31 06:39:15 +00:00
worker.send(info);
worker.on('message', touchMaster);
});
cluster.on('exit', function (worker, code, signal) {
console.info('[MASTER] Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal);
workers = workers.map(function (w) {
if (worker !== w) {
return w;
}
return null;
}).filter(function (w) {
return w;
});
2015-11-19 07:42:20 +00:00
//console.log('WARNING: worker spawning turned off for debugging ');
fork();
});
fork();