BaseApplication.js
166 lines
| 6.5 KiB
| application/javascript
|
JavascriptLexer
|
|
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); | |||
| }, | |||
| }); | |||
| }); |
