BLOGE
0.9.8-RC1在线版 · 事实校验 2026-09-15 · English
第 15 章 —— 状态机
承诺: 读完本章后,你将知道什么时候一个工作流已经超出了单张 DAG 的表达能力,需要用
state_machine来描述;你也会学会如何建模事件驱动迁移、超时和守卫条件,并让生命周期状态显式可见,而不是藏在一堆分支和标志位里。
学习目标
- 识别什么时候问题更适合用命名状态和迁移来表达,而不是继续堆分支 graph。
- 定义
initial、普通和terminal状态,并把状态内部的本地工作放进嵌入式 graph。 - 分清事件迁移、守卫迁移、自动迁移和超时迁移各自的职责。
- 在上线前就设置好
max_transitions和max_state_visits这类安全上限,避免坏循环变成生产事故。 - 知道什么时候该用状态机,什么时候 graph 或
session仍然更简单。
前置条件
- 第 5 章——做决策的分支 —— 状态迁移解决的问题和 graph 分支不同
- 第 12 章 —— 等待世界的回应 —— 事件驱动迁移仍然依赖同样的外部信号模型
- 第 13 章 —— 持久执行 —— 状态机的检查点与超时也站在持久执行基础上
- 第 14 章 —— 多轮 Session —— 有助于对比“对话轮次”和“生命周期状态”
源示例
| 文件 | 展示内容 |
|---|---|
ch14/order-lifecycle-state-machine.bloge | draft → review → processing → completed 的订单生命周期,并带超时回退 |
ch14/ticket-state-machine.bloge | 带 assign / escalate / resolve / close 路径的客服工单生命周期 |
OrderLifecycleStateMachineExample.java | 使用 StateMachineBuilder 的 Java Fluent API 版本 |
bloge-state-ext/README.md | 状态机运行时模型、超时语义和嵌套 session 说明 |
ReviewStateMachineWithSessionExample.java | 一个“状态机内嵌 session”的预告,下一章会展开 |
为什么这很重要
Graph 最擅长回答的问题是:在当前依赖关系下,什么现在可以执行?
状态机擅长回答的是另一个问题:这个业务对象现在处于什么状态?哪个事件会把它推进到下一个状态?
当流程存在回退、反复进入某个状态,或者必须让非实现人员也能一眼读懂生命周期时,这个区别就会变得非常关键。
例如:
- 一个订单可以从
draft进入pendingReview,又因为拒绝回到draft - 一张工单可以从
open进入triaging,再决定去assigned或escalated - 一个暂停中的 review 状态可以因为超时自动回退到前一个状态
这些规则也可以用分支、标志位和循环编码在一张 graph 中,但生命周期会隐含在 node 名称和条件表达式里。state_machine 则直接表示命名状态和状态迁移。
心智模型
状态机本质上是一个围绕每个状态局部工作而建立的事件驱动外壳。
| 组成部分 | 责任 |
|---|---|
StateMachineDef | 整个状态机的不可变定义 |
state | 一个命名的生命周期步骤,例如 draft、review、processing |
嵌入式 graph | 在该状态内部要执行的本地工作 |
| 迁移 | 在事件、超时或自动条件满足时前往另一个状态的规则 |
StateMachineExecutor | 启动状态机并递送外部事件 |
StateMachineCheckpoint | 可序列化快照,用于恢复与持久化 |
四种迁移样式最重要:
| 迁移样式 | 语法 | 适合什么 |
|---|---|---|