feat: add structured PARALLEL blocks with join-all tokens

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
0264408
2026-09-18 18:17:53 +08:00
co-authored by Cursor
parent 0e9bb4bd16
commit e4478656c1
31 changed files with 1300 additions and 62 deletions
+34
View File
@@ -486,6 +486,40 @@ components:
type: array
items:
type: object
properties:
id:
type: string
name:
type: string
kind:
type: string
enum: [APPROVAL, ACTION, PARALLEL]
candidates:
type: array
items:
type: string
policy:
type: string
enum: [ANY, ALL]
action:
type: string
due:
type: object
branches:
type: array
items:
type: object
properties:
id:
type: string
steps:
type: array
items:
type: object
transitions:
type: array
items:
type: object
transitions:
type: array
items:
+3 -2
View File
@@ -7,6 +7,7 @@
## 已完成
- ANY/ALL 会签/或签
- 结构化 PARALLEL 块(一层、join ALL、驳回否决整单)
- JDBC 存储(PostgreSQL / MySQL)+ 按方言 Flyway 基线
- 定义不可变多版本:`publish`;实例锁定 `definitionVersion`
- 条件路由 `StepTransition`:内置谓词 AST 或宿主 `RoutingCondition`(`ref` + `args`)
@@ -25,7 +26,7 @@
### 独立设计器(不进本仓库)
流程设计器是**单独产品**,消费上述 REST 与目录,不做成 ordo 模块。画布对齐引擎图(审批步、ACTION 步、边上的 `when`/`priority`,结束为 `to: null`),不引入 BPMN 网关/并行等引擎没有的语义。节点坐标等 layout 由设计器自存,不进入 `ProcessDefinition`。
流程设计器是**单独产品**,消费上述 REST 与目录,不做成 ordo 模块。画布对齐引擎图(审批步、ACTION 步、PARALLEL 块、边上的 `when`/`priority`,结束为 `to: null`),不引入自由 fork-join 网关。节点坐标等 layout 由设计器自存,不进入 `ProcessDefinition`。
启动时机:REST 契约与目录 SPI 落地之后。草稿由设计器/REST 文档存储,不进入引擎图版本。
@@ -36,6 +37,6 @@
## 后续新特性
上表「确定要做」之外,仍可能立项其他能力(例如表单/UI schema、子流程、并行 fork-join)。**多租户在另有明确决定前不进入计划。**
上表「确定要做」之外,仍可能立项其他能力(例如表单/UI schema、子流程、嵌套 PARALLEL / join ANY)。**多租户在另有明确决定前不进入计划。**
新特性立项时写入「开发计划」对应小节;完成后移到「已完成」,并更新 [usage.md](usage.md)。
+15 -3
View File
@@ -205,7 +205,8 @@ new ProcessDefinition("leave-request-routed", "Leave request",
| 字段 | 说明 |
|---|---|
| `startStep` | 可选。指定起始步骤 id;缺省为 `steps` 数组第一项。解析时会把该步旋到列表首位。 |
| `kind` | `APPROVAL`(默认)或 `ACTION`。 |
| `kind` | `APPROVAL`(默认)、`ACTION` 或 `PARALLEL`。 |
| `branches` | 仅 `PARALLEL`。至少 2 条分支;每条含 `id`、`steps`、`transitions`。禁止嵌套 PARALLEL。 |
| `candidates` / `policy` | 仅审批步。`policy` 默认 `ANY`。审批步至少一名候选人,禁止重复。 |
| `action` | 仅 ACTION 步,对应 `ActionHandler.execute` 的 key。审批步禁止带 `action`。 |
| `due` | 仅审批步。可选。`after` 为 ISO-8601 时长;`then` 为 `reassign` / `notify` / `goto`。进入该步时任务 `dueAt = now + after`。 |
@@ -218,6 +219,7 @@ new ProcessDefinition("leave-request-routed", "Leave request",
```
start → RUNNING
审批步:为每个候选人建 PENDING 任务
PARALLEL 步:为每条分支建立令牌并同时进入分支起点
ACTION 步:事务内记 PENDING 执行记录,提交后调 ActionHandler
approve / 路由结束 → APPROVED
reject(步被否决)→ REJECTED
@@ -270,7 +272,17 @@ ordo.cancel(instance.id(), "admin", "政策变更");
候选人创建任务前会经过 `AssigneeResolver.resolve(candidate, step, context)`,例如把角色名解析成用户 id。默认实现原样返回 candidate。
连续 ACTION 步会在同一次提交后依次执行,上限 32 跳,超出抛 `IllegalStateException`。
连续 ACTION 步会在同一次提交后依次执行,上限 32 跳(**每个 PARALLEL 分支各自计数**),超出抛 `IllegalStateException`。
### 5.1 结构化并行(PARALLEL)
主图仍是单线。`kind: PARALLEL` 是一个步骤,块内多条分支同时推进;全部完成后走该步在父图上的出边。不是 BPMN fork/join 网关。
JSON 嵌套写,引擎拍平存储。分支内边 `to: null` 表示**该分支完成并等待 join**,不是实例通过。PARALLEL 步自己的出边 `to: null` 才结束实例。
v1:至少 2 条分支;禁止套娃 PARALLEL;join 固定 ALL;任一分支按现有规则否决则整单 `REJECTED` 并 SKIPPED 其余 PENDING;`due.goto` 只能指向同一分支内的步骤。会签仍用单步 `candidates` + `ANY`/`ALL`。
事件:`PARALLEL_ENTERED`、`BRANCH_COMPLETED`(`detail` 为 branch id)、`PARALLEL_JOINED`。
## 6. 条件路由
@@ -382,7 +394,7 @@ ACTION 成功事件发生在提交之后,因此排在同轮事务内写入的
## 12. 存储
Flyway 脚本按方言分目录:`db/postgresql/migration`、`db/mysql/migration`(各一份当前 schema 的 `V1__baseline.sql`)。未设置 `spring.flyway.locations` 时,starter 按探测到的方言指向对应目录。已有 `flyway_schema_history` 的开发库需清空后重跑。表包括流程头 `ordo_process`、按 `(id, version)` 存储的定义/步骤/候选人/转移、实例(含 `definition_version`)、任务、`ordo_process_event`、`ordo_action_execution`。
Flyway 脚本按方言分目录:`db/postgresql/migration`、`db/mysql/migration`。未设置 `spring.flyway.locations` 时,starter 按探测到的方言指向对应目录。已有 `flyway_schema_history` 的开发库按版本追加迁移(PARALLEL 为 `V3__parallel_blocks.sql`)。表包括流程头 `ordo_process`、按 `(id, version)` 存储的定义/步骤(含 `parent_step_id` / `branch_id`)/候选人/转移、实例(含 `definition_version`)、任务、并行令牌 `ordo_instance_token`、`ordo_process_event`、`ordo_action_execution`。
自定义方言:实现 `SqlDialect` 并用 `META-INF/services` 注册,或提供 `SqlDialect` Bean。新增列时每个已支持方言目录各加一条迁移。