workflow-4-node
Version:
Workflow 4 Node is a .NET Workflow Foundation like framework for Node.js. The goal is to reach feature equivalence and beyond.
410 lines (356 loc) • 14.1 kB
JavaScript
"use strict";
var Activity = require("./activity");
var ActivityExecutionContext = require("./activityExecutionContext");
var ActivityExecutionState = require("./activityExecutionState");
var CallContext = require("./callContext");
var EventEmitter = require('events').EventEmitter;
var util = require("util");
var errors = require("../common/errors");
var _ = require("lodash");
var ActivityStateTracker = require("./activityStateTracker");
var enums = require("../common/enums");
var Bluebird = require("bluebird");
var asyncHelpers = require("../common/asyncHelpers");
var async = asyncHelpers.async;
var activityMarkup = require("./activityMarkup");
function ActivityExecutionEngine(contextOrActivity, instance) {
EventEmitter.call(this);
if (contextOrActivity instanceof Activity) {
this.rootActivity = contextOrActivity;
this.context = new ActivityExecutionContext(this);
this._isInitialized = false;
} else if (contextOrActivity instanceof ActivityExecutionContext) {
this.rootActivity = contextOrActivity.rootActivity;
this.context = contextOrActivity;
this.context.engine = this;
this._isInitialized = true;
} else if (_.isPlainObject(contextOrActivity)) {
this.rootActivity = activityMarkup.parse(contextOrActivity);
this.context = new ActivityExecutionContext(this);
this._isInitialized = false;
} else {
throw new TypeError("Argument 'contextOrActivity' is not an activity, context or a markup.");
}
this._rootState = null;
this._trackers = [];
this._hookContext();
this.updatedOn = null;
this.instance = instance || null;
}
util.inherits(ActivityExecutionEngine, EventEmitter);
Object.defineProperties(ActivityExecutionEngine.prototype, {
execState: {
get: function get() {
if (this._rootState) {
return this._rootState.execState;
} else {
return null;
}
}
},
version: {
get: function get() {
return this.rootActivity.version;
}
}
});
ActivityExecutionEngine.prototype._idle = {
toString: function toString() {
return enums.activityStates.idle;
}
};
ActivityExecutionEngine.prototype.isIdle = function (result) {
return result === this._idle;
};
ActivityExecutionEngine.prototype._initialize = function () {
if (!this._isInitialized) {
this.context.initialize(this.rootActivity);
this._isInitialized = true;
}
};
ActivityExecutionEngine.prototype._setRootState = function (state) {
var self = this;
if (!self._rootState) {
self._rootState = state;
self._rootState.on(Activity.states.cancel, function (args) {
self.emit(Activity.states.cancel, args);
});
self._rootState.on(Activity.states.complete, function (args) {
self.emit(Activity.states.complete, args);
});
self._rootState.on(Activity.states.end, function (args) {
self.updatedOn = new Date();
self.emit(Activity.states.end, args);
});
self._rootState.on(Activity.states.fail, function (args) {
self.emit(Activity.states.fail, args);
});
self._rootState.on(Activity.states.run, function (args) {
self.emit(Activity.states.run, args);
});
self._rootState.on(Activity.states.idle, function (args) {
self.emit(Activity.states.idle, args);
});
}
};
ActivityExecutionEngine.prototype._hookContext = function () {
var self = this;
self.context.on(Activity.states.run, function (args) {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = self._trackers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var t = _step.value;
t.activityStateChanged(args);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
});
self.context.on(Activity.states.end, function (args) {
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = self._trackers[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var t = _step2.value;
t.activityStateChanged(args);
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
});
self.context.on(enums.events.workflowEvent, function (args) {
self.emit(enums.events.workflowEvent, args);
});
};
ActivityExecutionEngine.prototype.addTracker = function (tracker) {
if (!_.isObject(tracker)) {
throw new TypeError("Parameter is not an object.");
}
this._trackers.push(new ActivityStateTracker(tracker));
};
ActivityExecutionEngine.prototype.removeTracker = function (tracker) {
var idx = -1;
for (var i = 0; i < this._trackers.length; i++) {
var t = this._trackers[i];
if (t._impl === tracker) {
idx = i;
break;
}
}
if (idx !== -1) {
this._trackers.splice(idx, 1);
}
};
ActivityExecutionEngine.prototype.start = async(regeneratorRuntime.mark(function _callee() {
var args,
_iteratorNormalCompletion3,
_didIteratorError3,
_iteratorError3,
_iterator3,
_step3,
a,
_args = arguments;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
this._verifyNotStarted();
this._initialize();
args = [new CallContext(this.context)];
_iteratorNormalCompletion3 = true;
_didIteratorError3 = false;
_iteratorError3 = undefined;
_context.prev = 6;
for (_iterator3 = _args[Symbol.iterator](); !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
a = _step3.value;
args.push(a);
}
_context.next = 14;
break;
case 10:
_context.prev = 10;
_context.t0 = _context["catch"](6);
_didIteratorError3 = true;
_iteratorError3 = _context.t0;
case 14:
_context.prev = 14;
_context.prev = 15;
if (!_iteratorNormalCompletion3 && _iterator3.return) {
_iterator3.return();
}
case 17:
_context.prev = 17;
if (!_didIteratorError3) {
_context.next = 20;
break;
}
throw _iteratorError3;
case 20:
return _context.finish(17);
case 21:
return _context.finish(14);
case 22:
_context.t1 = this;
_context.next = 25;
return this.rootActivity.start.apply(this.rootActivity, args);
case 25:
_context.t2 = _context.sent;
_context.t1._setRootState.call(_context.t1, _context.t2);
case 27:
case "end":
return _context.stop();
}
}
}, _callee, this, [[6, 10, 14, 22], [15,, 17, 21]]);
}));
ActivityExecutionEngine.prototype.invoke = function () {
var self = this;
self._verifyNotStarted();
self._initialize();
var args = [];
var _iteratorNormalCompletion4 = true;
var _didIteratorError4 = false;
var _iteratorError4 = undefined;
try {
for (var _iterator4 = arguments[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
var _a = _step4.value;
args.push(_a);
}
} catch (err) {
_didIteratorError4 = true;
_iteratorError4 = err;
} finally {
try {
if (!_iteratorNormalCompletion4 && _iterator4.return) {
_iterator4.return();
}
} finally {
if (_didIteratorError4) {
throw _iteratorError4;
}
}
}
args.unshift(new CallContext(self.context));
return new Bluebird(function (resolve, reject) {
try {
self._setRootState(self.context.getExecutionState(self.rootActivity));
self.once(Activity.states.end, function (eArgs) {
var reason = eArgs.reason;
var result = eArgs.result;
switch (reason) {
case Activity.states.complete:
resolve(result);
break;
case Activity.states.cancel:
reject(new errors.Cancelled());
break;
case Activity.states.idle:
resolve(self._idle);
break;
default:
result = result || new errors.ActivityRuntimeError("Unknown error.");
reject(result);
break;
}
});
self.rootActivity.start.apply(self.rootActivity, args);
} catch (e) {
reject(e);
}
});
};
ActivityExecutionEngine.prototype._verifyNotStarted = function () {
if (!(!this.execState || this.execState === enums.activityStates.complete)) {
throw new errors.ActivityStateExceptionError("Workflow has been already started.");
}
};
ActivityExecutionEngine.prototype.resumeBookmark = function (name, reason, result) {
var self = this;
self._initialize();
return new Bluebird(function (resolve, reject) {
try {
self._setRootState(self.context.getExecutionState(self.rootActivity));
if (self.execState === enums.activityStates.idle) {
(function () {
var bmTimestamp = self.context.getBookmarkTimestamp(name);
self.once(Activity.states.end, function (args) {
var _reason = args.reason;
var _result = args.result;
try {
if (_reason === enums.activityStates.complete || _reason === enums.activityStates.idle) {
var endBmTimestamp = self.context.getBookmarkTimestamp(name);
if (endBmTimestamp && endBmTimestamp === bmTimestamp) {
if (_reason === enums.activityStates.complete) {
reject(new errors.ActivityRuntimeError("Workflow has been completed before bookmark '" + name + "' reached."));
} else {
reject(new errors.Idle("Workflow has been gone to idle before bookmark '" + name + "' reached."));
}
} else {
resolve();
}
} else if (_reason === enums.activityStates.cancel) {
reject(new errors.ActivityRuntimeError("Workflow has been cancelled before bookmark '" + name + "' reached."));
} else if (_reason === enums.activityStates.fail) {
reject(_result);
}
} catch (e) {
reject(e);
}
});
self.context.resumeBookmarkExternal(name, reason, result);
})();
} else {
reject(new errors.ActivityRuntimeError("Cannot resume bookmark, while the workflow is not in the idle state."));
}
} catch (e) {
reject(e);
}
});
};
/* SERIALIZATION */
ActivityExecutionEngine.prototype.getStateAndPromotions = function (serializer, enablePromotions) {
if (serializer && !_.isObject(serializer)) {
throw new Error("Argument 'serializer' is not an object.");
}
this._initialize();
return this.context.getStateAndPromotions(serializer, enablePromotions);
};
ActivityExecutionEngine.prototype.setState = function (serializer, json) {
if (serializer && !_.isObject(serializer)) {
throw new Error("Argument 'serializer' is not an object.");
}
if (!_.isObject(json)) {
throw new TypeError("Argument 'json' is not an object.");
}
this._initialize();
this.updatedOn = new Date();
this.context.setState(serializer, json);
};
/* SERIALIZATION */
module.exports = ActivityExecutionEngine;
//# sourceMappingURL=activityExecutionEngine.js.map