什么是NodeJS工作流引擎
众所周知,NodeJS作为后端开发语言和运行环境,支持高并发、开发效率高,有口皆碑,但是大多用于数据CRUD管理
、中间层聚合
和中间层代理
等工具场景,很少深入到业务领域的核心。有许多用NodeJS开发的最小可用产品(MVP)
最终会另起炉灶重构,这是原因之一
究其根源,NodeJS作为业务开发平台,还缺少许多核心的基础构件,NodeJS工作流引擎
便是其一。CabloyJS 4.0重点开发了NodeJS工作流引擎,并作为内置的基础核心模块(同样是开源、免费),近一步拓展了NodeJS在后端的应用场景,为深入研发各类商业业务逻辑,提供了基础支撑
NodeJS工作流引擎的特点
- 更简便的配置:采用
JSON
进行流程定义的配置,告别XML配置文件的冗杂 - 流程定义:支持历史版本、支持启用/禁用
- 更清晰的架构:基于
分层机制
采用多个核心模块来搭建工作流引擎的架构,让工作流不再神秘,源码也不再叠床架屋
模块名称 | 说明 |
---|---|
a-flow | 流程定义、流程实例 |
a-flownode | 流程节点,包含基本的活动节点 的实现 |
a-flowtask | 流程任务,实现用户任务 节点的功能 |
a-flownodebooster | 流程节点增强包,包含更多活动节点 的实现,如:排他网关、并行网关、包含网关 |
a-flowbehavior | 包含常用的节点行为 的实现,如:超时处理 |
a-flowchart | 流程定义的可视化编辑 |
- 支持
业务流程
和审批流程
- 与
原子数据生命周期
结合,内置了一套基于原子数据的审批工作流
。参见:原子阶段(数据生命周期) - 与
表单验证
结合,支持分别配置不同流程节点的读取字段权限
和修改字段权限
。参见:表单验证 - 可通过
AOP
机制定制工作流逻辑。参见:AOP - 可通过
Listener
机制定制工作流逻辑 - 可通过
节点行为
机制实现类似Activiti
中边界事件
的功能,比如为活动节点
增加超时处理
的功能 - 开放式的架构,支持更多
流程节点
的定制开发 - 包含大量
测试驱动
代码,可快速上手使用工作流
安装演示模块
演示模块test-flow
包含业务表单+审批工作流
的完整代码示范,同时也包含NodeJS工作流引擎的所有测试用例。直接通过命令行安装模块test-flow
:
- 1$ npm run cli :store:sync test-flow
- 关于模块
test-flow
的更详细说明,参见:test-flow
工作流演示
- 新建一个草稿:
采购订单
- 选择要使用的
流程定义
,然后提交,草稿进入相应的审批流程
- 签收任务、并处理任务
- 流程结束,草稿转为
正式
副本
一个最简工作流定义
src/module/test-flow/backend/src/config/static/flowDef/set00_simple.js
- 1 {
- 2 listener: null,
- 3 process: {
- 4 nodes: [
- 5 {
- 6 id: 'startEvent_1',
- 7 name: 'Start',
- 8 type: 'startEventNone',
- 9 },
- 10 {
- 11 id: 'endEvent_1',
- 12 name: 'End',
- 13 type: 'endEventNone',
- 14 },
- 15 ],
- 16 edges: [
- 17 {
- 18 id: 'edge_1',
- 19 source: 'startEvent_1',
- 20 target: 'endEvent_1',
- 21 },
- 22 ],
- 23 },
- 24 }
名称 | 说明 |
---|---|
listener | 监听器,可监听flow/node/task各类事件 |
process.nodes | 流程节点 |
process.nodes.type | 流程节点类型 |
process.edges | 流程转移线 |
process.edges.source | 来源 |
process.edges.target | 去向 |
一个审批流程定义
src/module/test-flow/backend/src/config/static/flowDef/set01_atomUserTask.js
- 1 {
- 2 listener: null,
- 3 process: {
- 4 nodes: [
- 5 {
- 6 id: 'startEvent_1',
- 7 name: 'Drafting',
- 8 type: 'startEventAtom',
- 9 options: {
- 10 atom: {
- 11 module: moduleInfo.relativeName,
- 12 atomClassName: 'purchaseOrder',
- 13 },
- 14 conditionExpression: 'atom._flowDefKey===\'set01_atomUserTask\'',
- 15 },
- 16 },
- 17 {
- 18 id: 'activity_1',
- 19 name: 'Review',
- 20 type: 'activityUserTask',
- 21 options: {
- 22 assignees: {
- 23 // users: '1,2',
- 24 // roles: '1,2',
- 25 vars: 'flowUser',
- 26 },
- 27 confirmation: false,
- 28 bidding: false,
- 29 completionCondition: {
- 30 // passed: 1,
- 31 // rejected: '100%',
- 32 },
- 33 // rejectedNode:null,
- 34 // allowRejectTask: true,
- 35 // allowCancelFlow: false,
- 36 schema: {
- 37 write: [
- 38 'atomName',
- 39 {
- 40 name: 'description',
- 41 property: {
- 42 type: 'string',
- 43 ebType: 'text',
- 44 ebTitle: 'Description',
- 45 },
- 46 },
- 47 ],
- 48 },
- 49 },
- 50 },
- 51 {
- 52 id: 'endEvent_1',
- 53 name: 'End',
- 54 type: 'endEventAtom',
- 55 },
- 56 ],
- 57 edges: [
- 58 {
- 59 id: 'edge_1',
- 60 source: 'startEvent_1',
- 61 target: 'activity_1',
- 62 },
- 63 {
- 64 id: 'edge_2',
- 65 source: 'activity_1',
- 66 target: 'endEvent_1',
- 67 },
- 68 ],
- 69 },
- 70 }
- process.nodes.type
名称 | 说明 |
---|---|
startEventAtom | 开始事件节点(起草) :通过options.atom和options.conditionExpression与指定的Atom类型绑定。当指定的Atom提交时自动启动相匹配的工作流定义 |
activityUserTask | 用户任务节点 :可指定参与人、是否竞签、完成条件、读字段权限、写字段权限,等等 |
endEventAtom | 原子提交结束事件 节点 |
评论: