| 
									
										
										
										
											2015-11-18 11:44:22 +00:00
										 |  |  | '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 }
 | 
					
						
							| 
									
										
										
										
											2015-11-29 01:18:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-18 11:44:22 +00:00
										 |  |  |     // 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 = []; | 
					
						
							| 
									
										
										
										
											2015-11-29 01:18:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-18 11:44:22 +00:00
										 |  |  |       nodes.forEach(function (node) { | 
					
						
							| 
									
										
										
										
											2015-11-29 01:20:20 +00:00
										 |  |  |         if (/^\./.test(node)) { | 
					
						
							|  |  |  |           // ignore dot files
 | 
					
						
							| 
									
										
										
										
											2015-11-29 01:18:42 +00:00
										 |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-11-18 11:44:22 +00:00
										 |  |  |         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 = {}; | 
					
						
							| 
									
										
										
										
											2015-11-29 01:18:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-18 11:44:22 +00:00
										 |  |  |     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; | 
					
						
							| 
									
										
										
										
											2015-11-29 01:18:42 +00:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-11-18 11:44:22 +00:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return promise.then(function () { | 
					
						
							|  |  |  |       return servicesMap; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return loadServices().then(startServices); | 
					
						
							|  |  |  | }; |