feat: add audited task review and linked manual retries

This commit is contained in:
2026-09-17 21:57:53 +08:00
parent 571107f96d
commit a50d5faac7
43 changed files with 2096 additions and 57 deletions

77
docs/examples/recovery.md Normal file
View File

@@ -0,0 +1,77 @@
# 未知结果的核查与人工重试示例
完整源码:[SDK recovery/main.go](../../sdk/go/examples/recovery/main.go)。只处理本地模拟对象,不调用任何真实外部业务系统。接口细节见[人工恢复手册](../api/task-recovery.md)。
## 准备与运行
从仓库根目录执行,ORBIT_MYSQL_DSN通过环境指向专用开发库;已有基础服务时使用当前迁移及二进制。初始化创建独立演示应用,输出文件必须不存在:
```sh
go run ./cmd/orbit-migrate up
mkdir -p .local
chmod 700 .local
go run ./cmd/orbit-admin bootstrap \
--application recovery-demo --namespace default --environment development \
--queue recovery --worker-access --recovery-access \
--output .local/recovery.credentials.json
go run ./cmd/orbit
```
另开终端,从仓库根目录执行:
```sh
cd sdk/go
ORBIT_URL=http://127.0.0.1:8080 \
ORBIT_CREDENTIALS_FILE=../../.local/recovery.credentials.json \
go run ./examples/recovery
```
演示凭据为了完整运行同时包含Worker与人工管理权限;生产将它们分开。凭据文件0600、token不输出;也接受ORBIT_TOKEN/ORBIT_QUEUE_ID,环境值优先。
## 实际调用链
1. 用独立处理器名提交一个对象引用,领取/开始后报告UNKNOWN,任务进入NEEDS_REVIEW。
2. 模拟人工核实全部旧执行结束且操作未完成,带证据引用和版本ReviewTask,核查为FAILED。
3. 原键重报核查,确认同audit_id和deduplicated=true。
4. RetryTask声明可安全重新执行并指定新总预算60秒,取得retry_of指向原任务的新任务。
5. Worker开始新任务、报告SUCCEEDED;查询原任务仍FAILED、新任务SUCCEEDED。
6. 查询原任务操作列表及重试审计详情,排空并关闭Worker连接。
预期输出,标识由实际执行生成:
```text
source=<原任务ID> state=FAILED retry=<新任务ID> state=SUCCEEDED audit=<审计ID> operations=4
```
操作数包含本例受理、原结果、核查和人工重试;以本次实际查询为准。示例不删除任务、审计或尝试。重复运行创建独立演示任务,每次保留原历史。
## 接入片段
下方在已有客户端和已核实的current任务上下文中调用;完整imports/main及错误处理见源码。
```go
review, err := client.ReviewTask(ctx, current.ID, reviewKey, orbit.ReviewTaskRequest{
ExpectedRevision: current.Revision,
Reason: "已核实全部旧执行结束,操作未完成",
EvidenceRef: "evidence:reconciliation-001",
ExecutionSettled: true,
Outcome: orbit.TaskFailed,
Result: json.RawMessage(`{"confirmed":true}`),
})
if err != nil { return err }
retry, err := client.RetryTask(ctx, current.ID, retryKey, orbit.RetryTaskRequest{
ExpectedRevision: review.Task.Revision,
Reason: "同一业务操作可以安全重新执行",
EvidenceRef: "evidence:safe-retry-001",
SafeToRetry: true,
TaskTimeoutMS: 60000,
})
if err != nil { return err }
fmt.Println(retry.Task.ID, *retry.Task.RetryOf, retry.AuditID)
```
生产先持久化每次操作的key与完整请求,再发HTTP;响应丢失必须用原键、原版本、原结论重报。不能将同键回执中的新revision塞回原请求,不能看到UNKNOWN就直接RetryTask,也不能让审核按钮默认勾选“旧执行已结束”。
本程序为了清楚展示调用而使用单连接协议SDK及20秒总运行上限;错误非零退出,不包含持久化管理操作Outbox。失败后的任务须查询状态/历史再处理,60秒时限不意味着不确定效果会自动变成失败。持续Worker运行使用[自动Worker SDK](../sdk/worker-runtime.md)。
`make integration` 在隔离MySQL中运行本例及真实HTTP故障:核查和重试都在服务端提交后丢失响应,再原身份核对同一审计和子任务;旧Worker迟到成功只进入证据。外部证据的真实性与物理停止仍由管理流程核实。