deepify
Version:
DEEP Development Tools
151 lines (118 loc) • 3.33 kB
JavaScript
/**
* Created by AlexanderC on 8/18/15.
*/
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Thread = undefined;
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _child_process = require('child_process');
var _child_process2 = _interopRequireDefault(_child_process);
var _LambdaExecutionException = require('./Exception/LambdaExecutionException');
var _deepPackageManager = require('deep-package-manager');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
class Thread {
/**
* @param {Runtime} runtime
*/
constructor(runtime) {
this._runtime = runtime;
this._process = null;
this._timeoutIdx = null;
}
/**
* @param {Object} event
* @param {Boolean} measureTime
* @returns {Thread}
*/
run(event, measureTime) {
this._process = _child_process2.default.fork(Thread.WRAPPER, [JSON.stringify(this._runtime), JSON.stringify(event), measureTime], {
cwd: _path2.default.dirname(this._runtime.lambdaPath)
});
let contextSent = false;
let noPrematureFailCheck = false;
let onError = error => {
if (contextSent) {
console.error(`Sending context twice from Lambda (error thrown: ${error})`);
return;
}
contextSent = true;
this._runtime.fail(new _LambdaExecutionException.LambdaExecutionException(error));
this._cleanup();
};
// Kills lambda if execution time exceeded
this._timeoutIdx = setTimeout(() => {
if (contextSent) {
return;
}
noPrematureFailCheck = true;
onError(`The Lambda timeout of ${_deepPackageManager.Property_Lambda.MAX_TIMEOUT} seconds exceeded!`);
}, parseInt(_deepPackageManager.Property_Lambda.MAX_TIMEOUT) * 1000);
this._process.on('message', payload => {
if (contextSent) {
console.error(`Sending context twice from Lambda (payload: ${JSON.stringify(payload)})`);
return;
}
contextSent = true;
this._runtime[payload.state].apply(this._runtime, payload.args);
this._cleanup();
});
this._process.on('uncaughtException', onError);
this._process.on('error', onError);
this._process.on('exit', () => {
if (!contextSent && !noPrematureFailCheck) {
// hook to avoid msg sending delays...
setTimeout(() => {
if (!contextSent) {
onError('Premature exit!');
}
}, 200);
}
});
return this;
}
/**
* @param {String} error
* @private
*/
_onError(error) {
this._runtime.fail(new _LambdaExecutionException.LambdaExecutionException(error));
this._cleanup();
}
/**
* @returns {Thread}
* @private
*/
_cleanup() {
if (this._timeoutIdx) {
clearTimeout(this._timeoutIdx);
}
if (this._process) {
this._process.kill();
}
this._timeoutIdx = null;
this._process = null;
return this;
}
/**
* @returns {ChildProcess}
*/
get process() {
return this._process;
}
/**
* @returns {Runtime}
*/
get runtime() {
return this._runtime;
}
/**
* @returns {String}
*/
static get WRAPPER() {
return _path2.default.join(__dirname, 'thread_wrapper.js');
}
}
exports.Thread = Thread;