import { NFError } from "../error"; import { NFEventBus } from "../eventbus"; import { INFWaitState, NFNodeCfg, NFNodeType } from "../types"; import { NFNode } from "./node"; /** * 子流程节点:调用另一流程定义,子流程结束后继续 */ export class NFSubProcessNode extends NFNode{ callProcess:string; /** * 创建子流程节点。 * * @param cfg - 需含 `callProcess`(被调流程定义名) * @param process - 所属流程 * @throws `1101` 当缺少 `callProcess` */ constructor(cfg:NFNodeCfg,process){ super(cfg,process); this.type = NFNodeType.SUBPROCESS; this.callProcess = cfg.callProcess; if(!this.callProcess){ throw new NFError("1101",[this.name || this.id]); } } /** * 创建并启动子流程。子流程立即结束则合并变量并继续;否则挂起等待。 * * @throws `1300` 当被调流程定义不存在 */ async run(){ await super.run(); // 延迟加载,避免与 engine 循环依赖 const { NFEngine } = require('../engine'); const userId = this.process.entity?.nfUser?.userId; const childName = `${this.process.entity?.processName || 'proc'}-${this.id}-${Date.now()}`; const child = await NFEngine.createProcess(this.callProcess, childName, userId); if(!child){ throw new NFError("1300",[this.callProcess]); } await child.start(); if(child.entity.endTime){ const childParams = child.getParam(); if(childParams && typeof childParams === 'object'){ await this.process.setParams(childParams); } await NFEventBus.emit('node.leave',{ process:this.process, node:this, childProcessId:child.entity.processId }); const seq = this.process.nodeManager.getSequenceNode(this.id); if(seq){ await seq.run(); } return; } const state:INFWaitState = { kind: 'subprocess', nodeId: this.id, childProcessId: child.entity.processId }; await this.process.addWait(state); await NFEventBus.emit('node.leave',{ process:this.process, node:this, waiting:true, childProcessId:child.entity.processId }); } /** * 子流程结束后由父流程 `resumeWaits` 调用。 * * @returns 子流程仍在运行时为 `false`,否则为 `true` */ async resume(){ const wait = this.process.getWait(this.id); if(wait?.childProcessId){ const { NFEngine } = require('../engine'); const child = await NFEngine.getInstance(wait.childProcessId); if(child && !child.entity.endTime && !child.entity.deleteTime){ return false; } if(child){ const childParams = child.getParam(); if(childParams && typeof childParams === 'object'){ await this.process.setParams(childParams); } } } await this.process.removeWait(this.id); const seq = this.process.nodeManager.getSequenceNode(this.id); if(seq){ await seq.run(); } return true; } }