##// END OF EJS Templates
merge
merge

File last commit:

r0:7110eac54b19 v1.0.0 default
r3:e9671275b348 merge tip default
Show More
BaseApplication.js
166 lines | 6.5 KiB | application/javascript | JavascriptLexer
/ src / main / js / BaseApplication.js
cin
initial port of implab/web
r0 define([
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/when",
"cluster",
"os",
"implab/safe",
"./HttpResponse",
"./BaseResponse",
"dojo/Deferred",
"./HttpException",
"@implab/core/log/trace!"],
function (declare, lang, when, cluster, os, safe, HttpResponse, BaseResponse, Deferred, HttpException, trace) {
return declare(null, {
_container: null,
_serverPort: null,
_bindAddr: null,
_useCluster: null,
_requestConfig: null,
_restartFailedWorkers: null,
// модули, обрабатывающие запрос.
_modules: null,
_handlers: null,
constructor: function (options) {
safe.argumentNotNull(options, "options");
safe.argumentNotNull(options.container, "options.container");
safe.argumentNotNull(options.serverPort, "options.serverPort");
safe.argumentNotNull(options.useCluster, "options.useCluster");
safe.argumentNotEmptyString(options.bindAddr, "options.bindAddr");
safe.argumentNotEmptyString(options.requestConfig, "options.requestConfig");
this.options = options || {};
this._modules = [];
this._container = options.container;
this._serverPort = options.serverPort;
this._bindAddr = options.bindAddr;
this._useCluster = options.useCluster;
this._restartFailedWorkers = options.restartFailedWorkers;
this._requestConfig = options.requestConfig;
this._container.getService("httpHandlers").forEach(handler => {
this.handle(handler);
});
},
start: function () {
let me = this;
const numCPUs = os.cpus().length;
if (cluster.isMaster && me._useCluster) {
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function (worker, code, signal) {
if(me._restartFailedWorkers){
trace.log("worker {0} died. Signal {1}. Restarting ...", worker.process.pid, signal);
cluster.fork();
} else {
trace.log("worker {0} died.", worker.process.pid);
}
});
} else {
// Workers can share any TCP connection
// In this case it is an HTTP server
this.listen(this._serverPort, this._bindAddr);
}
},
listen: function (port, host) {
this._host = host;
this._port = port;
this._createServer(this.options, lang.hitch(this, "_handler")).listen(port, host, lang.hitch(this, "_listening"));
},
handle: function (module) {
if (module instanceof Function)
this._modules.push(module);
else if (module.invoke instanceof Function)
this._modules.push(function (req, next) {
return module.invoke(req, next);
});
else
throw "module shoud be a function or should have an invoke method";
},
_createServer: function () {
throw "NOT IMPLEMENTED";
},
_createRequest: function (container, req, res) {
return container.configure(this._requestConfig)
.then(function () {
let httpRequest = container.getService("httpRequest");
httpRequest.init(req, res);
return httpRequest;
});
},
//handler function to pass to the approperate server (like node.http)
_handler: function (req, res) {
let i = 0;
let me = this;
let requestContainer = this._container.createChildContainer();
when(this._createRequest(requestContainer, req, res), function (httpRequest) {
let next = function () {
if (i < me._modules.length) {
let module = me._modules[i];
i++;
try {
return when(module(httpRequest, next));
} catch (err) {
let d = new Deferred();
d.reject(err);
return d;
}
}
};
when(next(), function (result) {
if (!result)
throw "no response is provided, this is a serious bug";
if (result instanceof BaseResponse) {
result.send(res);
} else {
let httpResp = new HttpResponse();
httpResp.content = "BUG: " + result.toString();
httpResp.send(res);
}
requestContainer.dispose();
}).then(null, function (err) {
if (res.finished) {
trace.log("caught exception after the response is sent: {0}", err);
return;
}
let httpResp;
if (err instanceof HttpException)
httpResp = new HttpResponse(err.message, {
statusCode: err.code,
headers: err.headers
});
else
httpResp = new HttpResponse(err.toString(), {
statusCode: 500
});
httpResp.send(res);
requestContainer.dispose();
});
});
},
_listening: function () {
trace.log("Listening {0}:{1}", this._host, this._port);
},
});
});