118 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'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) {
 | 
						|
        if (/^\./.test(node)) {
 | 
						|
          // ignore dot files
 | 
						|
          return;
 | 
						|
        }
 | 
						|
        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);
 | 
						|
};
 |