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.memstoreSock = conf.memstoreSock; | ||||
|       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); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
| @ -20,6 +20,10 @@ module.exports.create = function (conf, deps, app) { | ||||
| 
 | ||||
|     return new PromiseA(function (resolve, reject) { | ||||
|       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); | ||||
|       } catch(e) { | ||||
|         reject(e); | ||||
|  | ||||
							
								
								
									
										113
									
								
								lib/services-loader.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								lib/services-loader.js
									
									
									
									
									
										Normal file
									
								
							| @ -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 app = express(); | ||||
|   var apiHandler; | ||||
|   var Services; | ||||
|   var memstore; | ||||
|   var sqlstores = {}; | ||||
|   var models = {}; | ||||
| @ -110,6 +111,8 @@ module.exports.create = function (webserver, info, state) { | ||||
|   app.use('/', caddyBugfix); | ||||
| 
 | ||||
|   return PromiseA.all([ | ||||
|     // TODO security on memstore
 | ||||
|     // TODO memstoreFactory.create
 | ||||
|     cstore.create({ | ||||
|       sock: 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) { | ||||
|       models.Config = tables; | ||||
|       return models.Config.Config.get().then(function (vhostsMap) { | ||||
|        | ||||
|         /* | ||||
|           // todo getDomainInfo
 | ||||
|           var utils = require('./utils'); | ||||
|           results.domains.forEach(function (domain) { | ||||
|             utils.getDomainInfo(domain.id); | ||||
|           }); | ||||
|         */ | ||||
|         // 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, { | ||||
|           memstore: memstore | ||||
|         , sqlstores: sqlstores | ||||
|         , clientSqlFactory: clientFactory | ||||
|         , systemSqlFactory: systemFactory | ||||
|         , Promise: PromiseA | ||||
|         }); | ||||
| 
 | ||||
|         function handleApi(req, res, next) { | ||||
|           var myApp; | ||||
| @ -183,29 +200,22 @@ module.exports.create = function (webserver, info, state) { | ||||
|             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(); | ||||
|           if (app.get('trust proxy')) { | ||||
|             myApp.set('trust proxy', app.get('trust proxy')); | ||||
|           } | ||||
|           apiHandler = require('./api-server').create( | ||||
|             { apppath: '../packages/apps/' | ||||
|             , apipath: '../packages/apis/' | ||||
|             , vhostsMap: vhostsMap | ||||
|             , server: webserver | ||||
|             , externalPort: info.externalPort | ||||
|             , apiPrefix: '/api' | ||||
|             } | ||||
|           , { app: myApp | ||||
|             , memstore: memstore | ||||
|             , sqlstores: sqlstores | ||||
|             , clientSqlFactory: clientFactory | ||||
|             , systemSqlFactory: systemFactory | ||||
|             //, handlePromise: require('./lib/common').promisableRequest;
 | ||||
|             //, handleRejection: require('./lib/common').rejectableRequest;
 | ||||
|             //, localPort: info.localPort
 | ||||
|             } | ||||
|           ).api; | ||||
|           apiHandler = require('./api-server').create(apiConf, { | ||||
|             app: myApp | ||||
|           , memstore: memstore | ||||
|           , sqlstores: sqlstores | ||||
|           , clientSqlFactory: clientFactory | ||||
|           , systemSqlFactory: systemFactory | ||||
|           //, handlePromise: require('./lib/common').promisableRequest;
 | ||||
|           //, handleRejection: require('./lib/common').rejectableRequest;
 | ||||
|           //, localPort: info.conf.localPort
 | ||||
|           , Promise: PromiseA | ||||
|           }, Services).api; | ||||
| 
 | ||||
|           apiHandler(req, res, next); | ||||
|         } | ||||
|  | ||||
| @ -86,6 +86,7 @@ | ||||
|     "mime-db": "^1.8.0", | ||||
|     "mime-types": "^2.0.10", | ||||
|     "ms": "^0.7.0", | ||||
|     "native-dns": "^0.7.0", | ||||
|     "negotiator": "^0.5.1", | ||||
|     "node-pre-gyp": "^0.6.4", | ||||
|     "node-uuid": "^1.4.4", | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user