@logicflow/engine 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +22 -0
  2. package/cjs/EventEmitter.js +70 -0
  3. package/cjs/FlowModel.js +252 -0
  4. package/cjs/Scheduler.js +278 -0
  5. package/cjs/constant/LogCode.js +31 -0
  6. package/cjs/constant/constant.js +23 -0
  7. package/cjs/expression/browserVm.js +69 -0
  8. package/cjs/expression/index.js +63 -0
  9. package/cjs/expression/nodeVm.js +53 -0
  10. package/cjs/index.js +161 -0
  11. package/cjs/nodes/BaseNode.js +243 -0
  12. package/cjs/nodes/StartNode.js +27 -0
  13. package/cjs/nodes/TaskNode.js +27 -0
  14. package/cjs/recorder/index.js +112 -0
  15. package/cjs/util/ID.js +12 -0
  16. package/cjs/util/global.js +32 -0
  17. package/cjs/util/storage.js +41 -0
  18. package/es/EventEmitter.d.ts +7 -0
  19. package/es/EventEmitter.js +68 -0
  20. package/es/FlowModel.d.ts +104 -0
  21. package/es/FlowModel.js +250 -0
  22. package/es/Scheduler.d.ts +51 -0
  23. package/es/Scheduler.js +276 -0
  24. package/es/constant/LogCode.d.ts +12 -0
  25. package/es/constant/LogCode.js +28 -0
  26. package/es/constant/constant.d.ts +14 -0
  27. package/es/constant/constant.js +20 -0
  28. package/es/expression/browserVm.d.ts +2 -0
  29. package/es/expression/browserVm.js +66 -0
  30. package/es/expression/index.d.ts +2 -0
  31. package/es/expression/index.js +60 -0
  32. package/es/expression/nodeVm.d.ts +2 -0
  33. package/es/expression/nodeVm.js +50 -0
  34. package/es/index.d.ts +47 -0
  35. package/es/index.js +156 -0
  36. package/es/nodes/BaseNode.d.ts +109 -0
  37. package/es/nodes/BaseNode.js +241 -0
  38. package/es/nodes/StartNode.d.ts +5 -0
  39. package/es/nodes/StartNode.js +25 -0
  40. package/es/nodes/TaskNode.d.ts +5 -0
  41. package/es/nodes/TaskNode.js +25 -0
  42. package/es/recorder/index.d.ts +9 -0
  43. package/es/recorder/index.js +110 -0
  44. package/es/util/ID.d.ts +2 -0
  45. package/es/util/ID.js +9 -0
  46. package/es/util/global.d.ts +5 -0
  47. package/es/util/global.js +26 -0
  48. package/es/util/storage.d.ts +6 -0
  49. package/es/util/storage.js +39 -0
  50. package/lib/main.js +1 -0
  51. package/package.json +87 -0
  52. package/types/EventEmitter.d.ts +7 -0
  53. package/types/FlowModel.d.ts +104 -0
  54. package/types/Scheduler.d.ts +51 -0
  55. package/types/constant/LogCode.d.ts +12 -0
  56. package/types/constant/constant.d.ts +14 -0
  57. package/types/expression/browserVm.d.ts +2 -0
  58. package/types/expression/index.d.ts +2 -0
  59. package/types/expression/nodeVm.d.ts +2 -0
  60. package/types/index.d.ts +47 -0
  61. package/types/nodes/BaseNode.d.ts +109 -0
  62. package/types/nodes/StartNode.d.ts +5 -0
  63. package/types/nodes/TaskNode.d.ts +5 -0
  64. package/types/recorder/index.d.ts +9 -0
  65. package/types/util/ID.d.ts +2 -0
  66. package/types/util/global.d.ts +5 -0
  67. package/types/util/storage.d.ts +6 -0
package/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # engine
2
+
3
+ 一个可以在JavaScript环境执行的流程引擎
4
+
5
+ ## 使用方式
6
+
7
+ ```js
8
+ import LogicFlowEngine from '@logicflow/engine';
9
+
10
+ const flowModel = new LogicFlowEngine({
11
+ graphData: {
12
+ nodes: [],
13
+ edges: [],
14
+ },
15
+ global: {
16
+ // 全局数据
17
+ }
18
+ });
19
+
20
+ flowModel.execute();
21
+
22
+ ```
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var EventEmitter = /** @class */ (function () {
4
+ function EventEmitter() {
5
+ this._events = {};
6
+ }
7
+ EventEmitter.prototype.on = function (evKey, callback, once) {
8
+ if (once === void 0) { once = false; }
9
+ evKey = evKey.trim();
10
+ if (!this._events[evKey]) {
11
+ this._events[evKey] = [];
12
+ }
13
+ this._events[evKey].push({
14
+ callback: callback,
15
+ once: !!once,
16
+ });
17
+ };
18
+ EventEmitter.prototype.emit = function (evt, eventArgs) {
19
+ var _this = this;
20
+ var events = this._events[evt] || [];
21
+ // 实际的处理 emit 方法
22
+ var doEmit = function (es) {
23
+ var length = es.length;
24
+ for (var i = 0; i < length; i++) {
25
+ if (!es[i]) {
26
+ // eslint-disable-next-line no-continue
27
+ continue;
28
+ }
29
+ var _a = es[i], callback = _a.callback, once = _a.once;
30
+ if (once) {
31
+ es.splice(i, 1);
32
+ if (es.length === 0) {
33
+ delete _this._events[evt];
34
+ }
35
+ length--;
36
+ i--;
37
+ }
38
+ callback.apply(_this, [eventArgs]);
39
+ }
40
+ };
41
+ doEmit(events);
42
+ };
43
+ EventEmitter.prototype.off = function (evt, callback) {
44
+ if (!evt) {
45
+ // evt 为空全部清除
46
+ this._events = {};
47
+ }
48
+ if (!callback) {
49
+ // evt 存在,callback 为空,清除事件所有方法
50
+ delete this._events[evt];
51
+ }
52
+ else {
53
+ // evt 存在,callback 存在,清除匹配的
54
+ var events = this._events[evt] || [];
55
+ var length_1 = events.length;
56
+ for (var i = 0; i < length_1; i++) {
57
+ if (events[i].callback === callback) {
58
+ events.splice(i, 1);
59
+ length_1--;
60
+ i--;
61
+ }
62
+ }
63
+ if (events.length === 0) {
64
+ delete this._events[evt];
65
+ }
66
+ }
67
+ };
68
+ return EventEmitter;
69
+ }());
70
+ exports.default = EventEmitter;
@@ -0,0 +1,252 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (_) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ var constant_1 = require("./constant/constant");
51
+ var ID_1 = require("./util/ID");
52
+ var Scheduler_1 = require("./Scheduler");
53
+ var LogCode_1 = require("./constant/LogCode");
54
+ var FlowModel = /** @class */ (function () {
55
+ function FlowModel(_a) {
56
+ var _this = this;
57
+ var nodeModelMap = _a.nodeModelMap, recorder = _a.recorder, _b = _a.context, context = _b === void 0 ? {} : _b, _c = _a.globalData, globalData = _c === void 0 ? {} : _c, _d = _a.startNodeType, startNodeType = _d === void 0 ? 'StartNode' : _d;
58
+ /**
59
+ * 当前流程模型中的所有节点,边会被转换成节点的incoming和outgoing属性。
60
+ */
61
+ this.nodeConfigMap = new Map();
62
+ /**
63
+ * 当前流程中开始节点组成的数组。
64
+ */
65
+ this.startNodes = [];
66
+ /**
67
+ * 用于存储全局数据,可以在流程中共享。
68
+ */
69
+ this.globalData = {};
70
+ // 流程包含的节点类型
71
+ this.nodeModelMap = nodeModelMap;
72
+ // 需要执行的队列
73
+ this.executeQueue = [];
74
+ // 执行中的任务
75
+ this.executingInstance = null;
76
+ // 外部传入的上下文,最终会传递给每个节点
77
+ this.context = context;
78
+ // 用于存储全局数据,可以在流程中共享。
79
+ this.globalData = globalData;
80
+ // 开始节点类型,在执行流程时,会从这些节点开始执行。
81
+ this.startNodeType = startNodeType;
82
+ this.isRunning = false;
83
+ this.scheduler = new Scheduler_1.default({
84
+ flowModel: this,
85
+ recorder: recorder,
86
+ });
87
+ this.scheduler.on(constant_1.EVENT_INSTANCE_COMPLETE, function (result) {
88
+ _this.onTaskFinished(result);
89
+ });
90
+ this.scheduler.on(constant_1.EVENT_INSTANCE_INTERRUPTED, function (result) {
91
+ _this.onTaskFinished(result);
92
+ });
93
+ }
94
+ FlowModel.prototype.setStartNodeType = function (startNodeType) {
95
+ this.startNodeType = startNodeType;
96
+ };
97
+ FlowModel.prototype.load = function (graphData) {
98
+ var _this = this;
99
+ var _a = graphData.nodes, nodes = _a === void 0 ? [] : _a, _b = graphData.edges, edges = _b === void 0 ? [] : _b;
100
+ nodes.forEach(function (node) {
101
+ if (_this.nodeModelMap.has(node.type)) {
102
+ var nodeConfig = {
103
+ id: node.id,
104
+ type: node.type,
105
+ properties: node.properties,
106
+ incoming: [],
107
+ outgoing: [],
108
+ };
109
+ _this.nodeConfigMap.set(node.id, nodeConfig);
110
+ if (node.type === _this.startNodeType) {
111
+ _this.startNodes.push(nodeConfig);
112
+ }
113
+ }
114
+ else {
115
+ console.warn("\u672A\u8BC6\u522B\u7684\u8282\u70B9\u7C7B\u578B: " + node.type);
116
+ }
117
+ });
118
+ edges.forEach(function (edge) {
119
+ var sourceNode = _this.nodeConfigMap.get(edge.sourceNodeId);
120
+ var targetNode = _this.nodeConfigMap.get(edge.targetNodeId);
121
+ if (sourceNode) {
122
+ sourceNode.outgoing.push({
123
+ id: edge.id,
124
+ properties: edge.properties,
125
+ target: edge.targetNodeId,
126
+ });
127
+ }
128
+ if (targetNode && targetNode.type !== _this.startNodeType) {
129
+ targetNode.incoming.push({
130
+ id: edge.id,
131
+ properties: edge.properties,
132
+ source: edge.sourceNodeId,
133
+ });
134
+ }
135
+ });
136
+ };
137
+ /**
138
+ * 执行流程
139
+ * 同一次执行,这次执行内部的节点执行顺序为并行。
140
+ * 多次执行,多次执行之间为串行。
141
+ * 允许一个流程多次执行,效率更高。
142
+ * 例如:
143
+ * 一个流程存在着两个开始节点,A和B,A和B的下一个节点都是C,C的下两个节点是D和E。
144
+ * 外部分别触发了A和B的执行,那么A和B的执行是串行的(也就是需要A执行完成后再执行B),但是D和E的执行是并行的。
145
+ * 如果希望A和B的执行是并行的,就不能使用同一个流程模型执行,应该初始化两个。
146
+ */
147
+ FlowModel.prototype.execute = function (params) {
148
+ return __awaiter(this, void 0, void 0, function () {
149
+ return __generator(this, function (_a) {
150
+ this.executeQueue.push(params);
151
+ if (this.isRunning) {
152
+ return [2 /*return*/];
153
+ }
154
+ this.isRunning = true;
155
+ this.createExecution();
156
+ return [2 /*return*/];
157
+ });
158
+ });
159
+ };
160
+ FlowModel.prototype.resume = function (params) {
161
+ return __awaiter(this, void 0, void 0, function () {
162
+ return __generator(this, function (_a) {
163
+ this.executeQueue.push(params);
164
+ if (this.isRunning) {
165
+ return [2 /*return*/];
166
+ }
167
+ this.isRunning = true;
168
+ this.createExecution();
169
+ return [2 /*return*/];
170
+ });
171
+ });
172
+ };
173
+ /**
174
+ * 创建节点实例
175
+ * @param nodeId 节点Id
176
+ * @returns 节点示例
177
+ */
178
+ FlowModel.prototype.createTask = function (nodeId) {
179
+ var nodeConfig = this.nodeConfigMap.get(nodeId);
180
+ var NodeModel = this.nodeModelMap.get(nodeConfig.type);
181
+ var task = new NodeModel({
182
+ nodeConfig: nodeConfig,
183
+ globalData: this.globalData,
184
+ context: this.context,
185
+ });
186
+ return task;
187
+ };
188
+ /**
189
+ * 更新流程全局数据
190
+ */
191
+ FlowModel.prototype.updateGlobalData = function (data) {
192
+ this.globalData = __assign(__assign({}, this.globalData), data);
193
+ };
194
+ FlowModel.prototype.onTaskFinished = function (result) {
195
+ var executionId = result.executionId;
196
+ if (executionId !== this.executionId) {
197
+ return;
198
+ }
199
+ var callback = this.executingInstance.callback;
200
+ if (callback) {
201
+ callback(result);
202
+ }
203
+ this.executingInstance = null;
204
+ if (this.executeQueue.length > 0) {
205
+ this.createExecution();
206
+ }
207
+ else {
208
+ this.isRunning = false;
209
+ }
210
+ };
211
+ FlowModel.prototype.createExecution = function () {
212
+ var _this = this;
213
+ var execParams = this.executeQueue.shift();
214
+ this.executingInstance = execParams;
215
+ if (execParams.executionId) {
216
+ this.executionId = execParams.executionId;
217
+ }
218
+ else {
219
+ this.executionId = ID_1.createExecId();
220
+ }
221
+ // 如果有taskId,那么表示恢复执行
222
+ if (execParams.taskId) {
223
+ this.scheduler.resume({
224
+ executionId: this.executionId,
225
+ taskId: execParams.taskId,
226
+ nodeId: execParams.nodeId,
227
+ data: execParams.data,
228
+ });
229
+ return;
230
+ }
231
+ if (execParams.nodeId) {
232
+ var nodeConfig = this.nodeConfigMap.get(execParams.nodeId);
233
+ if (!nodeConfig) {
234
+ execParams.onError(new Error(LogCode_1.getErrorMsg(LogCode_1.ErrorCode.NONE_NODE_ID) + "(" + execParams.nodeId + ")"));
235
+ return;
236
+ }
237
+ this.startNodes = [nodeConfig];
238
+ }
239
+ this.startNodes.forEach(function (startNode) {
240
+ _this.scheduler.addTask({
241
+ executionId: _this.executionId,
242
+ nodeId: startNode.id,
243
+ });
244
+ // 所有的开始节点都执行
245
+ });
246
+ this.scheduler.run({
247
+ executionId: this.executionId,
248
+ });
249
+ };
250
+ return FlowModel;
251
+ }());
252
+ exports.default = FlowModel;
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ extendStatics(d, b);
11
+ function __() { this.constructor = d; }
12
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13
+ };
14
+ })();
15
+ var __assign = (this && this.__assign) || function () {
16
+ __assign = Object.assign || function(t) {
17
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
18
+ s = arguments[i];
19
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
20
+ t[p] = s[p];
21
+ }
22
+ return t;
23
+ };
24
+ return __assign.apply(this, arguments);
25
+ };
26
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
27
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
28
+ return new (P || (P = Promise))(function (resolve, reject) {
29
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
30
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
31
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
32
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
33
+ });
34
+ };
35
+ var __generator = (this && this.__generator) || function (thisArg, body) {
36
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
37
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
38
+ function verb(n) { return function (v) { return step([n, v]); }; }
39
+ function step(op) {
40
+ if (f) throw new TypeError("Generator is already executing.");
41
+ while (_) try {
42
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
43
+ if (y = 0, t) op = [op[0] & 2, t.value];
44
+ switch (op[0]) {
45
+ case 0: case 1: t = op; break;
46
+ case 4: _.label++; return { value: op[1], done: false };
47
+ case 5: _.label++; y = op[1]; op = [0]; continue;
48
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
49
+ default:
50
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
51
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
52
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
53
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
54
+ if (t[2]) _.ops.pop();
55
+ _.trys.pop(); continue;
56
+ }
57
+ op = body.call(thisArg, _);
58
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
59
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
60
+ }
61
+ };
62
+ Object.defineProperty(exports, "__esModule", { value: true });
63
+ var EventEmitter_1 = require("./EventEmitter");
64
+ var constant_1 = require("./constant/constant");
65
+ var ID_1 = require("./util/ID");
66
+ /**
67
+ * 调度器
68
+ * 通过一个队列维护需要执行的节点,一个集合维护正在执行的节点
69
+ */
70
+ var Scheduler = /** @class */ (function (_super) {
71
+ __extends(Scheduler, _super);
72
+ function Scheduler(config) {
73
+ var _this = _super.call(this) || this;
74
+ _this.nodeQueueMap = new Map();
75
+ _this.taskRunningMap = new Map();
76
+ _this.flowModel = config.flowModel;
77
+ _this.recorder = config.recorder;
78
+ _this.currentTask = null;
79
+ return _this;
80
+ }
81
+ /**
82
+ * 添加一个任务到队列中。
83
+ * 1. 由流程模型将所有的开始节点添加到队列中。
84
+ * 2. 当一个节点执行完成后,将后续的节点添加到队列中。
85
+ */
86
+ Scheduler.prototype.addTask = function (nodeParam) {
87
+ var executionId = nodeParam.executionId;
88
+ if (!this.nodeQueueMap.has(executionId)) {
89
+ this.nodeQueueMap.set(executionId, []);
90
+ }
91
+ var currentTaskQueue = this.nodeQueueMap.get(executionId);
92
+ currentTaskQueue.push(nodeParam);
93
+ };
94
+ /**
95
+ * 调度器执行下一个任务
96
+ * 1. 提供给流程模型,用户开始执行第一个任务。
97
+ * 2. 内部任务执行完成后,调用此方法继续执行下一个任务。
98
+ * 3. 当判断没有可以继续执行的任务后,触发流程结束事件。
99
+ */
100
+ Scheduler.prototype.run = function (runParams) {
101
+ var nodeQueue = this.nodeQueueMap.get(runParams.executionId);
102
+ if (nodeQueue.length > 0) {
103
+ this.nodeQueueMap.set(runParams.executionId, []);
104
+ for (var i = 0; i < nodeQueue.length; i++) {
105
+ var currentNode = nodeQueue[i];
106
+ var taskId = ID_1.createTaskId();
107
+ var taskParam = __assign(__assign({}, currentNode), { taskId: taskId });
108
+ this.pushTaskToRunningMap(taskParam);
109
+ this.exec(taskParam);
110
+ }
111
+ }
112
+ else if (!this.hasRunningTask(runParams.executionId)) {
113
+ // 当一个流程在nodeQueueMap和taskRunningMap中都不存在执行的节点时,说明这个流程已经执行完成。
114
+ this.emit(constant_1.EVENT_INSTANCE_COMPLETE, {
115
+ executionId: runParams.executionId,
116
+ nodeId: runParams.nodeId,
117
+ taskId: runParams.taskId,
118
+ status: constant_1.FlowStatus.COMPLETED,
119
+ });
120
+ }
121
+ };
122
+ /**
123
+ * 恢复某个任务的执行。
124
+ * 可以自定义节点手动实现流程中断,然后通过此方法恢复流程的执行。
125
+ */
126
+ Scheduler.prototype.resume = function (resumeParam) {
127
+ return __awaiter(this, void 0, void 0, function () {
128
+ var model;
129
+ return __generator(this, function (_a) {
130
+ switch (_a.label) {
131
+ case 0:
132
+ this.pushTaskToRunningMap({
133
+ executionId: resumeParam.executionId,
134
+ nodeId: resumeParam.nodeId,
135
+ taskId: resumeParam.taskId,
136
+ });
137
+ model = this.flowModel.createTask(resumeParam.nodeId);
138
+ return [4 /*yield*/, model.resume(__assign(__assign({}, resumeParam), { next: this.next.bind(this) }))];
139
+ case 1:
140
+ _a.sent();
141
+ return [2 /*return*/];
142
+ }
143
+ });
144
+ });
145
+ };
146
+ // 流程执行过程中出错,停止执行
147
+ Scheduler.prototype.stop = function (data) {
148
+ console.log('stop', data);
149
+ };
150
+ Scheduler.prototype.pushTaskToRunningMap = function (taskParam) {
151
+ var executionId = taskParam.executionId, taskId = taskParam.taskId;
152
+ if (!this.taskRunningMap.has(executionId)) {
153
+ var runningMap = new Map();
154
+ this.taskRunningMap.set(executionId, runningMap);
155
+ }
156
+ this.taskRunningMap.get(executionId).set(taskId, taskParam);
157
+ };
158
+ Scheduler.prototype.removeTaskFromRunningMap = function (taskParam) {
159
+ var executionId = taskParam.executionId, taskId = taskParam.taskId;
160
+ if (!taskId)
161
+ return;
162
+ var runningMap = this.taskRunningMap.get(executionId);
163
+ if (!runningMap)
164
+ return;
165
+ runningMap.delete(taskId);
166
+ };
167
+ Scheduler.prototype.hasRunningTask = function (executionId) {
168
+ var runningMap = this.taskRunningMap.get(executionId);
169
+ if (!runningMap)
170
+ return false;
171
+ if (runningMap.size === 0) {
172
+ this.taskRunningMap.delete(executionId);
173
+ return false;
174
+ }
175
+ return true;
176
+ };
177
+ Scheduler.prototype.exec = function (taskParam) {
178
+ return __awaiter(this, void 0, void 0, function () {
179
+ var model, execResult;
180
+ return __generator(this, function (_a) {
181
+ switch (_a.label) {
182
+ case 0:
183
+ model = this.flowModel.createTask(taskParam.nodeId);
184
+ return [4 /*yield*/, model.execute({
185
+ executionId: taskParam.executionId,
186
+ taskId: taskParam.taskId,
187
+ nodeId: taskParam.nodeId,
188
+ next: this.next.bind(this),
189
+ })];
190
+ case 1:
191
+ execResult = _a.sent();
192
+ if (execResult && execResult.status === constant_1.FlowStatus.INTERRUPTED) {
193
+ this.interrupted({
194
+ execResult: execResult,
195
+ taskParam: taskParam,
196
+ });
197
+ this.saveTaskResult({
198
+ executionId: taskParam.executionId,
199
+ nodeId: taskParam.nodeId,
200
+ taskId: taskParam.taskId,
201
+ nodeType: execResult.nodeType,
202
+ properties: execResult.properties,
203
+ outgoing: [],
204
+ extraInfo: {
205
+ status: execResult.status,
206
+ detail: execResult.detail,
207
+ },
208
+ });
209
+ this.removeTaskFromRunningMap(taskParam);
210
+ }
211
+ return [2 /*return*/];
212
+ }
213
+ });
214
+ });
215
+ };
216
+ Scheduler.prototype.interrupted = function (_a) {
217
+ var execResult = _a.execResult, taskParam = _a.taskParam;
218
+ this.emit(constant_1.EVENT_INSTANCE_INTERRUPTED, {
219
+ executionId: taskParam.executionId,
220
+ status: constant_1.FlowStatus.INTERRUPTED,
221
+ nodeId: taskParam.nodeId,
222
+ taskId: taskParam.taskId,
223
+ detail: execResult.detail,
224
+ });
225
+ };
226
+ Scheduler.prototype.next = function (data) {
227
+ return __awaiter(this, void 0, void 0, function () {
228
+ var _this = this;
229
+ return __generator(this, function (_a) {
230
+ switch (_a.label) {
231
+ case 0:
232
+ if (data.outgoing && data.outgoing.length > 0) {
233
+ data.outgoing.forEach(function (item) {
234
+ _this.addTask({
235
+ executionId: data.executionId,
236
+ nodeId: item.target,
237
+ });
238
+ });
239
+ }
240
+ return [4 /*yield*/, this.saveTaskResult(data)];
241
+ case 1:
242
+ _a.sent();
243
+ this.removeTaskFromRunningMap(data);
244
+ this.run({
245
+ executionId: data.executionId,
246
+ nodeId: data.nodeId,
247
+ taskId: data.taskId,
248
+ });
249
+ return [2 /*return*/];
250
+ }
251
+ });
252
+ });
253
+ };
254
+ /**
255
+ * 为了防止多次添加导致
256
+ */
257
+ Scheduler.prototype.saveTaskResult = function (data) {
258
+ return __awaiter(this, void 0, void 0, function () {
259
+ return __generator(this, function (_a) {
260
+ switch (_a.label) {
261
+ case 0: return [4 /*yield*/, this.recorder.addTask({
262
+ executionId: data.executionId,
263
+ taskId: data.taskId,
264
+ nodeId: data.nodeId,
265
+ nodeType: data.nodeType,
266
+ timestamp: Date.now(),
267
+ properties: data.properties,
268
+ })];
269
+ case 1:
270
+ _a.sent();
271
+ return [2 /*return*/];
272
+ }
273
+ });
274
+ });
275
+ };
276
+ return Scheduler;
277
+ }(EventEmitter_1.default));
278
+ exports.default = Scheduler;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var _a, _b;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.getWarningMsg = exports.getErrorMsg = exports.WarningCode = exports.ErrorCode = void 0;
5
+ var ErrorCode;
6
+ (function (ErrorCode) {
7
+ // 模型数据错误
8
+ ErrorCode[ErrorCode["NONE_START_NODE"] = 1000] = "NONE_START_NODE";
9
+ ErrorCode[ErrorCode["NONE_NODE_ID"] = 1001] = "NONE_NODE_ID";
10
+ // 表达式错误
11
+ ErrorCode[ErrorCode["NO_DOCUMENT_BODY"] = 2001] = "NO_DOCUMENT_BODY";
12
+ })(ErrorCode = exports.ErrorCode || (exports.ErrorCode = {}));
13
+ var WarningCode;
14
+ (function (WarningCode) {
15
+ WarningCode[WarningCode["NONE_START_NODE_IN_DATA"] = 2000] = "NONE_START_NODE_IN_DATA";
16
+ WarningCode[WarningCode["START_NODE_INCOMING"] = 2001] = "START_NODE_INCOMING";
17
+ // 表达式判断异常
18
+ WarningCode[WarningCode["EXPRESSION_EXEC_ERROR"] = 3000] = "EXPRESSION_EXEC_ERROR";
19
+ })(WarningCode = exports.WarningCode || (exports.WarningCode = {}));
20
+ var errorMsgMapCn = (_a = {},
21
+ _a[ErrorCode.NONE_START_NODE] = '未找到入度为0的节点',
22
+ _a[ErrorCode.NONE_NODE_ID] = '流程数据中存在没有此节点',
23
+ _a[ErrorCode.NO_DOCUMENT_BODY] = '找不到document.body, 请在DOM加载完成后再执行',
24
+ _a);
25
+ var warningMsgMapCn = (_b = {},
26
+ _b[WarningCode.NONE_START_NODE_IN_DATA] = '初始化数据中未找到入度为0的节点',
27
+ _b[WarningCode.START_NODE_INCOMING] = '开始节点不允许被连入',
28
+ _b[WarningCode.EXPRESSION_EXEC_ERROR] = '表达式执行异常',
29
+ _b);
30
+ exports.getErrorMsg = function (code) { return "error[" + code + "]: " + errorMsgMapCn[code]; };
31
+ exports.getWarningMsg = function (code) { return "warning[" + code + "]: " + warningMsgMapCn[code]; };
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TaskStatus = exports.FlowStatus = exports.EVENT_INSTANCE_INTERRUPTED = exports.EVENT_INSTANCE_COMPLETE = exports.BASE_START_NODE = void 0;
4
+ // baseType
5
+ exports.BASE_START_NODE = 'start';
6
+ // event name
7
+ exports.EVENT_INSTANCE_COMPLETE = 'instance:complete';
8
+ exports.EVENT_INSTANCE_INTERRUPTED = 'instance:interrupted';
9
+ // flow status
10
+ var FlowStatus;
11
+ (function (FlowStatus) {
12
+ FlowStatus["COMPLETED"] = "completed";
13
+ FlowStatus["INTERRUPTED"] = "interrupted";
14
+ FlowStatus["RUNNING"] = "running";
15
+ FlowStatus["ERROR"] = "error";
16
+ })(FlowStatus = exports.FlowStatus || (exports.FlowStatus = {}));
17
+ // task status
18
+ var TaskStatus;
19
+ (function (TaskStatus) {
20
+ TaskStatus["SUCCESS"] = "success";
21
+ TaskStatus["ERROR"] = "error";
22
+ TaskStatus["INTERRUPTED"] = "interrupted";
23
+ })(TaskStatus = exports.TaskStatus || (exports.TaskStatus = {}));