UNPKG

@logicflow/engine

Version:

a process engine for javascript

179 lines 7.21 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Scheduler = void 0; const tslib_1 = require("tslib"); const EventEmitter_1 = tslib_1.__importDefault(require("./EventEmitter")); const utils_1 = require("./utils"); const constant_1 = require("./constant"); /** * 调度器 * 通过一个队列维护需要执行的节点,一个集合维护正在执行的节点 */ class Scheduler extends EventEmitter_1.default { constructor(config) { super(); this.nodeQueueMap = new Map(); this.actionRunningMap = new Map(); this.flowModel = config.flowModel; this.recorder = config.recorder; } /** * 添加一个任务到队列中。 * 1. 由流程模型将所有的开始及诶带你添加到队列中 * 2. 当一个节点执行完成后,将后续的节点添加到队列中 * @param nodeParam */ addAction(nodeParam) { const { executionId } = nodeParam; if (!this.nodeQueueMap.has(executionId)) { this.nodeQueueMap.set(executionId, []); } const currentActionQueue = this.nodeQueueMap.get(executionId); if (currentActionQueue) { currentActionQueue.push(nodeParam); } console.log('this.nodeQueueMap--->>>', this.nodeQueueMap); } pushActionToRunningMap(actionParam) { var _a; const { executionId, actionId } = actionParam; if (!this.actionRunningMap.has(executionId)) { const runningMap = new Map(); this.actionRunningMap.set(executionId, runningMap); } if (actionId) { (_a = this.actionRunningMap.get(executionId)) === null || _a === void 0 ? void 0 : _a.set(actionId, actionParam); } } removeActionFromRunningMap(actionParam) { const { executionId, actionId } = actionParam; if (!actionId) return; const runningMap = this.actionRunningMap.get(executionId); if (!runningMap) return; runningMap.delete(actionId); } /** * 为了防止多次添加导致 * @param actionParam */ saveActionResult(actionParam) { var _a; (_a = this.recorder) === null || _a === void 0 ? void 0 : _a.addActionRecord(Object.assign({ timestamp: Date.now() }, actionParam)); } hasRunningAction(executionId) { const runningMap = this.actionRunningMap.get(executionId); if (!runningMap) return false; if (runningMap.size === 0) { this.actionRunningMap.delete(executionId); return false; } return true; } /** * 调度器执行下一个任务 * 1. 提供给流程模型,用户开始执行第一个任务 * 2. 内部任务执行完成后,调用此方法继续执行下一个任务 * 3. 当判断没有可以继续执行的任务后,触发流程结束事件 * @param runParam */ run(runParam) { const nodeQueue = this.nodeQueueMap.get(runParam.executionId); // 将同一个 executionId 当前待执行的节点一起执行 // 避免出现某一个节点执行时间过长,导致其他节点等待时间过长 while (nodeQueue === null || nodeQueue === void 0 ? void 0 : nodeQueue.length) { const currentNode = nodeQueue.pop(); const actionId = (0, utils_1.createActionId)(); const actionParam = Object.assign(Object.assign({}, currentNode), { actionId }); this.pushActionToRunningMap(actionParam); this.exec(actionParam); } if (!this.hasRunningAction(runParam.executionId)) { // 当一个流程在 nodeQueueMap 和 actionRunningMap 中都不存在执行的节点时,说明这个流程已经执行完成。 this.emit(constant_1.EVENT_INSTANCE_COMPLETE, Object.assign(Object.assign({}, runParam), { status: constant_1.FlowStatus.COMPLETED })); } } next(data) { if (data.outgoing && data.outgoing.length > 0) { data.outgoing.forEach((item) => { if (item.result) { this.addAction({ executionId: data.executionId, nodeId: item.target, }); } }); } this.saveActionResult(data); this.removeActionFromRunningMap(data); this.run(data); } /** * 恢复某个任务的执行 * 可以自定义节点手动实现流程中断,然后通过此方法恢复流程的执行 * @param resumeParam */ resume(resumeParam) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const { executionId, actionId, nodeId } = resumeParam; this.pushActionToRunningMap({ executionId, actionId, nodeId, }); const model = this.flowModel.createAction(nodeId); yield (model === null || model === void 0 ? void 0 : model.resume(Object.assign(Object.assign({}, resumeParam), { next: this.next.bind(this) }))); }); } // 中断时,触发事件 interrupted(execResult) { this.emit(constant_1.EVENT_INSTANCE_INTERRUPTED, execResult); } // 报错时,触发事件 error(execResult) { this.emit(constant_1.EVENT_INSTANCE_ERROR, execResult); } exec(actionParam) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const { executionId, actionId, nodeId } = actionParam; const model = this.flowModel.createAction(nodeId); const execResult = yield (model === null || model === void 0 ? void 0 : model.execute({ executionId, actionId, nodeId, next: this.next.bind(this), })); if (execResult) { const { nodeType, properties, outgoing, status, detail } = execResult; const actionResult = { // actionParam executionId, actionId, nodeId, // execResult nodeType, properties, outgoing, status, detail, }; if ((execResult === null || execResult === void 0 ? void 0 : execResult.status) === constant_1.FlowStatus.INTERRUPTED) { this.interrupted(execResult); this.saveActionResult(actionResult); this.removeActionFromRunningMap(actionParam); } if ((execResult === null || execResult === void 0 ? void 0 : execResult.status) === constant_1.FlowStatus.ERROR) { this.error(execResult); this.saveActionResult(actionResult); this.removeActionFromRunningMap(actionParam); } } // TODO: 考虑停下所有的任务 }); } } exports.Scheduler = Scheduler; exports.default = Scheduler; //# sourceMappingURL=Scheduler.js.map