load services
This commit is contained in:
parent
96b7c9bb65
commit
78178eb43d
|
@ -78,6 +78,10 @@ cluster.on('online', function (worker) {
|
||||||
info.conf.ipcKey = conf.ipcKey;
|
info.conf.ipcKey = conf.ipcKey;
|
||||||
info.conf.memstoreSock = conf.memstoreSock;
|
info.conf.memstoreSock = conf.memstoreSock;
|
||||||
info.conf.sqlite3Sock = conf.sqlite3Sock;
|
info.conf.sqlite3Sock = conf.sqlite3Sock;
|
||||||
|
// TODO get this from db config instead
|
||||||
|
var config = require('../config');
|
||||||
|
info.conf.primaryNameserver = config.primaryNameserver;
|
||||||
|
info.conf.nameservers = config.nameservers;
|
||||||
worker.send(info);
|
worker.send(info);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,10 @@ module.exports.create = function (conf, deps, app) {
|
||||||
|
|
||||||
return new PromiseA(function (resolve, reject) {
|
return new PromiseA(function (resolve, reject) {
|
||||||
try {
|
try {
|
||||||
|
// TODO dynamic requires are a no-no
|
||||||
|
// can we statically generate a require-er? on each install?
|
||||||
|
// module.exports = { {{pkgpath}}: function () { return require({{pkgpath}}) } }
|
||||||
|
// requirer[pkgpath]()
|
||||||
route.route = require(pkgpath).create(conf, deps, app);
|
route.route = require(pkgpath).create(conf, deps, app);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
reject(e);
|
reject(e);
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports.create = function (conf, deps) {
|
||||||
|
var PromiseA = deps.Promise;
|
||||||
|
|
||||||
|
function loadService(node) {
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
return new PromiseA(function (resolve) {
|
||||||
|
// process.nextTick runs at the end of the current event loop
|
||||||
|
// we actually want time to pass so that potential api traffic can be handled
|
||||||
|
setTimeout(function () {
|
||||||
|
var servicepath = path.join(conf.servicespath, node);
|
||||||
|
var pkg;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// TODO no package should be named package.json
|
||||||
|
pkg = require(servicepath + '/package.json');
|
||||||
|
resolve({
|
||||||
|
pkg: pkg
|
||||||
|
, name: node
|
||||||
|
, service: require(servicepath)
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
} catch(e) {
|
||||||
|
// TODO report errors to admin console
|
||||||
|
// TODO take sha256sum of e.stack and store in db with tick for updatedAt
|
||||||
|
console.error("[Service] could not require service '" + servicepath + "'");
|
||||||
|
console.error(e.stack);
|
||||||
|
//services.push({ error: e });
|
||||||
|
resolve(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadServices() {
|
||||||
|
var fs = PromiseA.promisifyAll(require('fs'));
|
||||||
|
|
||||||
|
// deps : { memstore, sqlstores, clientSqlFactory, systemSqlFactory }
|
||||||
|
|
||||||
|
// XXX this is a no-no (file system access in a worker, cannot be statically analyzed)
|
||||||
|
// TODO regenerate a static file of all requires on each install
|
||||||
|
// TODO read system config db to find which services auto-start
|
||||||
|
// TODO allow certain apis access to certain services
|
||||||
|
return fs.readdirAsync(conf.servicespath).then(function (nodes) {
|
||||||
|
var promise = PromiseA.resolve();
|
||||||
|
var services = [];
|
||||||
|
|
||||||
|
nodes.forEach(function (node) {
|
||||||
|
promise = promise.then(function () {
|
||||||
|
return loadService(node).then(function (srv) {
|
||||||
|
if (!srv) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
services.push(srv);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise.then(function () {
|
||||||
|
return services;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startService(srv) {
|
||||||
|
return new PromiseA(function (resolve) {
|
||||||
|
// process.nextTick runs at the end of the current event loop
|
||||||
|
// we actually want time to pass so that potential api traffic can be handled
|
||||||
|
setTimeout(function () {
|
||||||
|
try {
|
||||||
|
PromiseA.resolve(srv.service.create(conf, deps)).then(resolve, function (e) {
|
||||||
|
console.error("[Service] couldn't promise service");
|
||||||
|
console.error(e.stack);
|
||||||
|
resolve(null);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
} catch(e) {
|
||||||
|
console.error("[Service] couldn't start service");
|
||||||
|
console.error(e.stack);
|
||||||
|
resolve(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startServices(services) {
|
||||||
|
var promise = PromiseA.resolve();
|
||||||
|
var servicesMap = {};
|
||||||
|
|
||||||
|
services.forEach(function (srv) {
|
||||||
|
promise = promise.then(function () {
|
||||||
|
return startService(srv).then(function (service) {
|
||||||
|
if (!service) {
|
||||||
|
// TODO log
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
srv.service = service;
|
||||||
|
servicesMap[srv.name] = srv;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise.then(function () {
|
||||||
|
return servicesMap;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadServices().then(startServices);
|
||||||
|
};
|
|
@ -11,6 +11,7 @@ module.exports.create = function (webserver, info, state) {
|
||||||
var express = require('express-lazy');
|
var express = require('express-lazy');
|
||||||
var app = express();
|
var app = express();
|
||||||
var apiHandler;
|
var apiHandler;
|
||||||
|
var Services;
|
||||||
var memstore;
|
var memstore;
|
||||||
var sqlstores = {};
|
var sqlstores = {};
|
||||||
var models = {};
|
var models = {};
|
||||||
|
@ -110,6 +111,8 @@ module.exports.create = function (webserver, info, state) {
|
||||||
app.use('/', caddyBugfix);
|
app.use('/', caddyBugfix);
|
||||||
|
|
||||||
return PromiseA.all([
|
return PromiseA.all([
|
||||||
|
// TODO security on memstore
|
||||||
|
// TODO memstoreFactory.create
|
||||||
cstore.create({
|
cstore.create({
|
||||||
sock: info.conf.memstoreSock
|
sock: info.conf.memstoreSock
|
||||||
, connect: info.conf.memstoreSock
|
, connect: info.conf.memstoreSock
|
||||||
|
@ -146,14 +149,28 @@ module.exports.create = function (webserver, info, state) {
|
||||||
return require('../lib/schemes-config').create(sqlstores.config).then(function (tables) {
|
return require('../lib/schemes-config').create(sqlstores.config).then(function (tables) {
|
||||||
models.Config = tables;
|
models.Config = tables;
|
||||||
return models.Config.Config.get().then(function (vhostsMap) {
|
return models.Config.Config.get().then(function (vhostsMap) {
|
||||||
|
// TODO the core needs to be replacable in one shot
|
||||||
|
// rm -rf /tmp/walnut/; tar xvf -C /tmp/walnut/; mv /srv/walnut /srv/walnut.{{version}}; mv /tmp/walnut /srv/
|
||||||
|
// this means that any packages must be outside, perhaps /srv/walnut/{boot,core,packages}
|
||||||
|
var apiConf = {
|
||||||
|
apppath: '../packages/apps/'
|
||||||
|
, apipath: '../packages/apis/'
|
||||||
|
, servicespath: path.join(__dirname, '..', 'packages', 'services')
|
||||||
|
, vhostsMap: vhostsMap
|
||||||
|
, server: webserver
|
||||||
|
, externalPort: info.conf.externalPort
|
||||||
|
, primaryNameserver: info.conf.primaryNameserver
|
||||||
|
, nameservers: info.conf.nameservers
|
||||||
|
, apiPrefix: '/api'
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
Services = require('./services-loader').create(apiConf, {
|
||||||
// todo getDomainInfo
|
memstore: memstore
|
||||||
var utils = require('./utils');
|
, sqlstores: sqlstores
|
||||||
results.domains.forEach(function (domain) {
|
, clientSqlFactory: clientFactory
|
||||||
utils.getDomainInfo(domain.id);
|
, systemSqlFactory: systemFactory
|
||||||
});
|
, Promise: PromiseA
|
||||||
*/
|
});
|
||||||
|
|
||||||
function handleApi(req, res, next) {
|
function handleApi(req, res, next) {
|
||||||
var myApp;
|
var myApp;
|
||||||
|
@ -183,29 +200,22 @@ module.exports.create = function (webserver, info, state) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// apiHandler = require('./vhost-server').create(info.localPort, vhostsdir).create(webserver, app)
|
// apiHandler = require('./vhost-server').create(info.conf.localPort, vhostsdir).create(webserver, app)
|
||||||
myApp = express();
|
myApp = express();
|
||||||
if (app.get('trust proxy')) {
|
if (app.get('trust proxy')) {
|
||||||
myApp.set('trust proxy', app.get('trust proxy'));
|
myApp.set('trust proxy', app.get('trust proxy'));
|
||||||
}
|
}
|
||||||
apiHandler = require('./api-server').create(
|
apiHandler = require('./api-server').create(apiConf, {
|
||||||
{ apppath: '../packages/apps/'
|
app: myApp
|
||||||
, apipath: '../packages/apis/'
|
, memstore: memstore
|
||||||
, vhostsMap: vhostsMap
|
, sqlstores: sqlstores
|
||||||
, server: webserver
|
, clientSqlFactory: clientFactory
|
||||||
, externalPort: info.externalPort
|
, systemSqlFactory: systemFactory
|
||||||
, apiPrefix: '/api'
|
//, handlePromise: require('./lib/common').promisableRequest;
|
||||||
}
|
//, handleRejection: require('./lib/common').rejectableRequest;
|
||||||
, { app: myApp
|
//, localPort: info.conf.localPort
|
||||||
, memstore: memstore
|
, Promise: PromiseA
|
||||||
, sqlstores: sqlstores
|
}, Services).api;
|
||||||
, clientSqlFactory: clientFactory
|
|
||||||
, systemSqlFactory: systemFactory
|
|
||||||
//, handlePromise: require('./lib/common').promisableRequest;
|
|
||||||
//, handleRejection: require('./lib/common').rejectableRequest;
|
|
||||||
//, localPort: info.localPort
|
|
||||||
}
|
|
||||||
).api;
|
|
||||||
|
|
||||||
apiHandler(req, res, next);
|
apiHandler(req, res, next);
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@
|
||||||
"mime-db": "^1.8.0",
|
"mime-db": "^1.8.0",
|
||||||
"mime-types": "^2.0.10",
|
"mime-types": "^2.0.10",
|
||||||
"ms": "^0.7.0",
|
"ms": "^0.7.0",
|
||||||
|
"native-dns": "^0.7.0",
|
||||||
"negotiator": "^0.5.1",
|
"negotiator": "^0.5.1",
|
||||||
"node-pre-gyp": "^0.6.4",
|
"node-pre-gyp": "^0.6.4",
|
||||||
"node-uuid": "^1.4.4",
|
"node-uuid": "^1.4.4",
|
||||||
|
|
|
@ -22,5 +22,9 @@ Math.random = function () {
|
||||||
if (cluster.isMaster) {
|
if (cluster.isMaster) {
|
||||||
require('./boot/master');
|
require('./boot/master');
|
||||||
} else {
|
} else {
|
||||||
|
/*
|
||||||
|
alternately we could use this and then check require.main
|
||||||
|
cluster.setupMaster({ exec : "app.js", });
|
||||||
|
*/
|
||||||
require('./boot/worker').create(null);
|
require('./boot/worker').create(null);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue