Files
orbit/docs/examples/workflow-recovery.md

91 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 提交后回执丢失:核查、暂停与有证据恢复
[完整源码](../../examples/workflow-recovery/main.go)使用真实Orbit、自动Worker和本机HTTP渠道夹具。夹具先保存外部提交结果,再直接关闭连接,确保Worker实际遇到传输错误。流程进入NEEDS_REVIEW后,程序在受控夹具中模拟一个已经核实事实的管理员,逐项提交恢复决定。
这是一份可运行的SDK接入与故障示例。夹具数据仅在本次进程内保存;真实系统需要持久证据和真实授权,不能把下面的演示核查逻辑接成任意业务的自动放行。
## 1. 启动
需要Go 1.27.1、MySQL 8.4+,设置专用`ORBIT_MYSQL_DSN`。仓库根目录执行:
```sh
go run ./cmd/orbit-migrate up
mkdir -p .local
chmod 700 .local
go run ./cmd/orbit-admin bootstrap \
--application workflow-recovery-example --namespace default --environment development \
--queue workflows --workflow-access --workflow-run-access --worker-access \
--workflow-control-access --workflow-recovery-access --workflow-audit-access \
--output .local/workflow-recovery.credentials.json
go run ./cmd/orbit
```
初始化一次;原凭据文件不会被覆盖。另开终端,从仓库根目录运行:
```sh
cd examples
ORBIT_URL=http://127.0.0.1:8080 \
ORBIT_CREDENTIALS_FILE=../.local/workflow-recovery.credentials.json \
go run ./workflow-recovery
```
开发凭据包含定义、启动、Worker、控制、恢复及审计权限,便于单命令演示。正式接入应使用HTTPS/WSS,并为业务Worker与管理员分别签发所需权限;Worker执行权不自动授予恢复权。
## 2. 故障与完整调用顺序
流程包含publish和record两个顺序任务。输入为原操作身份及精确序号9007199254740993;publish只允许一次请求尝试,安全策略为RECONCILE_ONLY。record只在前一步被核实成功并解除控制门控后处理已确认回执。
1. 创建定义、发布v1并启动;Worker向本机渠道POST一次。渠道保存结果,然后关闭连接,不返回HTTP响应。
2. 处理器返回普通error。Orbit保留UNKNOWN尝试,任务和流程进入NEEDS_REVIEW,不重发POST。
3. 查询当前步骤、任务及尝试,确认唯一尝试已结束、Worker处理器已退出且结果报告已确认,再显式PAUSE流程。
4. 用原操作身份GET渠道证据,核对operation_id、状态CONFIRMED及精确序号。夹具能证明这是唯一一次提交,且提交处理已经结束;真实系统必须另行证明历史执行已结清,仅有一次GET成功不够。
5. `ReviewWorkflowTask`提交执行结论:当前实例版本、任务版本、execution_settled=true、结果及证据引用。使用原键原命令再调用一次,确认同一审计回执。
6. 等待核查结果被内部消费,重新读取步骤及实例版本;`ResolveWorkflowStep`确认逻辑步骤成功,保留原激活。
7. `ContinueWorkflow`声明核查事项已解决。此时仍为paused,record步骤保持BLOCKED,没有任务被提前建立。
8. 查询三条管理审计,核对操作人、原因和同一证据引用;再单独调用`ControlWorkflow(RESUME)`释放暂停。
9. Worker完成record,流程成功;查询原尝试仍是UNKNOWN,原实例截止未变,最后排空Worker。
每个管理决定都有独立稳定操作键。核查使用实例revision,控制使用control_revision,两者不可互换。读到新事实后重新核查再形成下一条命令;不能自动把STATE_CONFLICT改为最新版本重报。
## 3. SDK关键字段
完整程序使用[六类恢复API中的三个方法](../api/workflow-recovery.md)。执行核查示意:
```go
command := orbit.ReviewWorkflowTaskRequest{
WorkflowRecoveryDecision: orbit.WorkflowRecoveryDecision{
ExpectedRevision: currentStep.Revision,
Reason: "已核实原操作、结果和所有相关执行已结束",
EvidenceRef: evidenceRef,
},
TaskID: task.ID, ExpectedTaskRevision: task.Revision,
ExecutionSettled: true,
Outcome: orbit.TaskSucceeded, Result: verifiedResult,
}
receipt, err := client.ReviewWorkflowTask(ctx, workflowID, reviewKey, command)
if err != nil { return err }
// receipt是管理事务的冻结回执,下一项决定前应读取新的当前事实。
```
示例证据引用形如`evidence:local-fixture/<operation>`,明确表示本地受控夹具,不能冒充持久业务证据。平台只保存受控引用及审计,不请求该地址。真实证据应由接入方按权限、保留及审计要求持久保存。
## 4. 输出与历史保护
程序先打印可查询的操作身份和workflow ID,最终应输出:
```text
recovery_verified=true state=SUCCEEDED submissions=1 unknown_history_preserved=true review_deduplicated=true pause_preserved=true audits=3 sequence=9007199254740993 worker_drained=true
```
这些标志来自实际API和Worker统计:只发生1次外部POST;同键核查返回同一audit_id;task-review、step-resolve、continue三条审计具有原因、主体和证据;恢复没有解除PAUSE;旧UNKNOWN尝试和结束时间没有改写;两项业务任务均已结束并确认。
最终任务的权威结果可以是SUCCEEDED,同时原尝试保留UNKNOWN,两者并不矛盾。核查增加新的决定和证据,不能抹去当时无法确认结果的事实。
## 5. 失败及重跑边界
本次运行最多45秒,Worker排空最多5秒。任何身份、证据、结果或版本不符都会非零退出;失败不会自动调用RetryWorkflowStep、换键重发外部POST或解除核查。
重新运行命令创建新的独立演示流程,不是对上一流程的恢复。生产接入方必须持久保存每条命令和幂等键;响应未知时使用原命令原键核对,旧版本冲突需要重新核查。示例退出时关闭本机HTTP夹具与Worker,平台流程和历史保留;若中途失败,夹具停止后不能再用其内存结果作为后续人工恢复依据。
`make integration`运行此示例以及独立SDK中的六类恢复回归;另有节点强杀、恢复代次和原预算验证。记录见[P4/P5核对](../reports/phase-4-5.md)。这不替代真实业务的幂等、权限、证据和生产故障恢复验收。