feat: pin running instances to immutable published definition versions
Replace register/replace with publish so new graphs can ship without rewriting old ones, and keep in-flight work on the version it started with. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+3
-6
@@ -7,7 +7,8 @@
|
||||
## 已完成
|
||||
|
||||
- ANY/ALL 会签/或签
|
||||
- JDBC 存储(PostgreSQL)+ Flyway V1–V6
|
||||
- JDBC 存储(PostgreSQL)+ Flyway V1–V7
|
||||
- 定义不可变多版本:`publish`;实例锁定 `definitionVersion`
|
||||
- 条件路由 `StepTransition` + `RoutingCondition`
|
||||
- ACTION + `ActionHandler`;执行记录持久化
|
||||
- 发起人撤回 `WITHDRAWN`
|
||||
@@ -21,10 +22,6 @@
|
||||
|
||||
下列能力已纳入计划,尚未实现。实现顺序可按依赖调整,但范围本身不从计划中拿掉。
|
||||
|
||||
### 定义不可变多版本
|
||||
|
||||
当前同 `id` 用 `replace` 整体替换;存在 `RUNNING` 实例时拒绝。计划改为定义不可变多版本:新版本不改写旧版本;运行中实例锁定发起时所用版本。
|
||||
|
||||
### MySQL 方言
|
||||
|
||||
当前 JDBC DDL/冲突处理面向 PostgreSQL。计划增加 MySQL 方言(及对应测试),通过 dialect 层扩展,而不是只支持一种库。
|
||||
@@ -41,7 +38,7 @@
|
||||
|
||||
流程设计器是**单独产品**,消费上述 REST 与目录,不做成 ordo 模块。画布对齐引擎图(审批步、ACTION 步、边上的 `when`/`priority`,结束为 `to: null`),不引入 BPMN 网关/并行等引擎没有的语义。节点坐标等 layout 由设计器自存,不进入 `ProcessDefinition`。
|
||||
|
||||
启动时机:REST 契约、目录 SPI、定义不可变多版本落地之后。当前 `replace` + 无版本锁定不适合作为设计器保存/发布模型。
|
||||
启动时机:REST 契约与目录 SPI 落地之后。草稿由设计器/REST 文档存储,不进入引擎图版本。
|
||||
|
||||
## 暂不在计划中
|
||||
|
||||
|
||||
+15
-17
@@ -12,7 +12,7 @@ Ordo 是嵌入宿主进程的审批引擎,入口是 `OrdoEngine`。
|
||||
|
||||
产品边界:不做业务表单、用户体系、多租户;不内置设计器 UI。业务字段放在 `ProcessContext`(不可变 `Map<String, Object>`)。当前也**没有** REST;HTTP 仍由宿主自建。计划中的可选 REST 与独立设计器见 [roadmap.md](roadmap.md)。
|
||||
|
||||
开发计划(尚未提供,见 [roadmap.md](roadmap.md)):定义不可变多版本、MySQL 方言、可选 REST + 目录 SPI。
|
||||
开发计划(尚未提供,见 [roadmap.md](roadmap.md)):MySQL 方言、可选 REST + 目录 SPI。
|
||||
|
||||
## 2. 模块与接入
|
||||
|
||||
@@ -61,12 +61,12 @@ OrdoEngine ordo = new InMemoryOrdoEngine();
|
||||
ordo:
|
||||
enabled: true
|
||||
definitions:
|
||||
location: classpath*:ordo/*.json # 启动时对每个 JSON 调用 replace
|
||||
location: classpath*:ordo/*.json # 启动时对每个 JSON 调用 publish
|
||||
due:
|
||||
poll-ms: 0 # >0 时轮询 processDue;默认不调度
|
||||
```
|
||||
|
||||
启动加载使用 `replace`:无 `RUNNING` 实例则整图替换;有运行中实例则保留库里的定义。
|
||||
启动加载使用 `publish`:图与 latest 相同则不升版本;不同则写入新版本。运行中实例继续锁定发起时所用版本。
|
||||
|
||||
宿主用 `@Bean` 覆盖默认扩展点:
|
||||
|
||||
@@ -81,14 +81,14 @@ ordo:
|
||||
|
||||
## 3. 流程定义
|
||||
|
||||
每个定义有 `id`、`name`、步骤列表、转移列表。步骤 id 在定义内唯一。每个步骤必须至少有一条出边(结束用 `to = null`)。同一 `from` 上 `priority` 不能重复。
|
||||
每个定义有 `id`、引擎分配的 `version`、`name`、步骤列表、转移列表。步骤 id 在定义内唯一。每个步骤必须至少有一条出边(结束用 `to = null`)。同一 `from` 上 `priority` 不能重复。
|
||||
|
||||
### 3.1 代码构建
|
||||
|
||||
线性(每步无条件进下一步,最后一步结束):
|
||||
|
||||
```java
|
||||
ordo.register(ProcessDefinition.linear("leave-request", "Leave request", List.of(
|
||||
ordo.publish(ProcessDefinition.linear("leave-request", "Leave request", List.of(
|
||||
ApprovalStep.single("manager", "Manager approval", "maria"),
|
||||
ApprovalStep.single("hr", "HR approval", "henry")
|
||||
)));
|
||||
@@ -113,10 +113,9 @@ new ProcessDefinition("leave-request-routed", "Leave request",
|
||||
));
|
||||
```
|
||||
|
||||
`register`:同 id 已存在则 `DefinitionAlreadyExistsException`。
|
||||
`replace`:整图覆盖;存在该定义的 `RUNNING` 实例则 `DefinitionInUseException`。
|
||||
`publish`:该 `id` 尚无版本则写入 v1;与 latest 的 id/name/steps/transitions 相同则返回 latest 不插入;否则插入 `latest + 1`。运行中实例不阻止发布。调用方构造的 `ProcessDefinition` 版本为 0;入库后由引擎分配从 1 起的单调版本。JSON 不要写 `version`,出现则忽略。
|
||||
|
||||
当前**没有**运行中实例锁定所用版本:`replace` 成功后新实例用新图,旧已结束实例仍按当时落库的任务理解历史。
|
||||
`start(definitionId)` 使用 latest。实例带 `definitionVersion`;审批、到期、撤回、取消均按该版本取图,不跟随后续 `publish`。
|
||||
|
||||
### 3.2 JSON
|
||||
|
||||
@@ -303,19 +302,20 @@ ACTION 成功事件发生在提交之后,因此排在同轮事务内写入的
|
||||
|---|---|---|
|
||||
| `queryTasks(TaskQuery, PageRequest)` | assignee、instanceId、definitionId、status、createdFrom/To | 创建时间降序 |
|
||||
| `queryInstances(InstanceQuery, PageRequest)` | definitionId、status、initiator、startedFrom/To | 开始时间降序 |
|
||||
| `queryDefinitions(PageRequest)` | 无过滤 | 定义 id 升序 |
|
||||
| `queryDefinitions(PageRequest)` | 每个 id 的 latest | 定义 id 升序 |
|
||||
| `queryDefinitionVersions(id, PageRequest)` | 单 id 全部版本 | version 降序 |
|
||||
| `queryHistory(instanceId, PageRequest)` | 单实例 | 发生时间升序 |
|
||||
| `queryActionExecutions(instanceId, PageRequest)` | 单实例 | 开始时间升序 |
|
||||
|
||||
`TaskQuery.any().withAssignee("maria").withStatus(TaskStatus.PENDING)` 等 with 方法返回新对象。字段 `null` 表示不按该维过滤。
|
||||
|
||||
便捷方法(不分页):`findInstance`、`findTask`、`findTasks`、`findPendingTasksByAssignee`、`findPendingTasksByInstanceId`。
|
||||
便捷方法(不分页):`findInstance`、`findTask`、`findTasks`、`findPendingTasksByAssignee`、`findPendingTasksByInstanceId`、`findDefinition(id)` / `findDefinition(id, version)`。
|
||||
|
||||
## 10. `OrdoEngine` 一览
|
||||
|
||||
| 方法 | 说明 |
|
||||
|---|---|
|
||||
| `register` / `replace` | 登记 / 整图替换定义 |
|
||||
| `publish` | 发布不可变图版本(相等则 no-op) |
|
||||
| `start` | 发起;可选 `ProcessContext` |
|
||||
| `approve` / `reject` | 办理当前 PENDING 任务 |
|
||||
| `reassign` | 当前办理人把 PENDING 任务转给他人 |
|
||||
@@ -323,7 +323,7 @@ ACTION 成功事件发生在提交之后,因此排在同轮事务内写入的
|
||||
| `withdraw` | 发起人撤回 |
|
||||
| `cancel` | 管理员/系统取消(引擎不鉴权角色) |
|
||||
| `find*` | 按 id / 待办索引读取 |
|
||||
| `queryTasks` / `queryInstances` / `queryDefinitions` | 分页列表 |
|
||||
| `queryTasks` / `queryInstances` / `queryDefinitions` / `queryDefinitionVersions` | 分页列表 |
|
||||
| `queryHistory` / `queryActionExecutions` | 实例审计与 ACTION 记录 |
|
||||
|
||||
## 11. 异常
|
||||
@@ -332,9 +332,7 @@ ACTION 成功事件发生在提交之后,因此排在同轮事务内写入的
|
||||
|
||||
| 类型 | 何时 |
|
||||
|---|---|
|
||||
| `DefinitionAlreadyExistsException` | `register` 撞 id |
|
||||
| `DefinitionNotFoundException` | `start` 等找不到定义 |
|
||||
| `DefinitionInUseException` | `replace` 时仍有 RUNNING 实例 |
|
||||
| `DefinitionNotFoundException` | `start` 等找不到 latest,或实例锁定的 version 不存在 |
|
||||
| `InstanceNotFoundException` | 撤回/取消等找不到实例 |
|
||||
| `InstanceAlreadyCompletedException` | 对非 RUNNING 实例完成/撤回/取消 |
|
||||
| `TaskNotFoundException` | 任务 id 不存在 |
|
||||
@@ -347,12 +345,12 @@ ACTION 成功事件发生在提交之后,因此排在同轮事务内写入的
|
||||
|
||||
## 12. 存储
|
||||
|
||||
Flyway 脚本在 `ordo-storage-jdbc` 的 `db/migration`(V1–V6)。表包括定义/步骤/候选人/转移、实例、任务、`ordo_process_event`、`ordo_action_execution`。
|
||||
Flyway 脚本在 `ordo-storage-jdbc` 的 `db/migration`(V1–V7)。表包括流程头 `ordo_process`、按 `(id, version)` 存储的定义/步骤/候选人/转移、实例(含 `definition_version`)、任务、`ordo_process_event`、`ordo_action_execution`。
|
||||
|
||||
多 JVM 共享同一库时,多步写入走 `TransactionExecutor`,完成任务/实例用条件更新(仍 PENDING / 仍 RUNNING 才改),避免双花。
|
||||
|
||||
## 13. 未提供能力
|
||||
|
||||
开发计划中(见 [roadmap.md](roadmap.md)):定义不可变多版本、MySQL 方言、可选 REST + 目录 SPI。独立设计器不进本仓库,等 REST、目录与多版本定义之后再做。
|
||||
开发计划中(见 [roadmap.md](roadmap.md)):MySQL 方言、可选 REST + 目录 SPI。独立设计器不进本仓库,等 REST 与目录之后再做。
|
||||
|
||||
暂不在计划中:多租户、设计器 UI。当前 REST 由宿主自建。
|
||||
|
||||
Reference in New Issue
Block a user