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

147 lines
9.0 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.
# 流程人工核查与恢复 API / SDK
状态:六类内部恢复已接入公共HTTP和独立SDK。所有路径以 `/v1/workflows/{id}/recovery/` 开头,均为POST,要求 `workflows:recover`、全部固定队列范围、Bearer凭据、稳定Idempotency-Key及application/json。成功首次与重复响应均为200。身份、读查询、错误码见[实例接口](workflows.md)。
恢复只针对NEEDS_REVIEW实例。SDK不会自动重试、补齐声明、刷新版本或生成新键。核查前应读取当前实例、当前步骤、相关任务及外部证据;每次新决定使用当前版本,响应未知则用原决定原键核对。输入和结果最多256 KiB,请求体总计最多512 KiB。
## 1. 公共字段
所有请求包含WorkflowRecoveryDecision的**扁平字段**:
| 字段 | 必填与语义 |
| --- | --- |
| expected_revision | 必填,当前实例的非零revision十进制字符串,不能用control_revision替代 |
| reason | 必填,1–1024个Unicode字符;不允许全空白或NUL |
| evidence_ref | 必填,1–512个Unicode字符,不含空白或控制字符;平台不访问引用、不存放秘密 |
步骤类请求还包含WorkflowStepDecision的扁平字段:step_key(固定定义步骤名,最多64个ASCII字符)、activation_id(当前32位激活ID)、expected_step_revision(当前非零步骤版本字符串)。实例版本、步骤版本及激活身份一起检查,旧激活不能操作新工作。
服务端检查待消费/隔离Inbox、历史任务归属、仍在执行的尝试及未释放许可。声明为true是操作者确认,不替代服务端验证。恢复不会重置原绝对截止、次数或业务关联;已有停止目标不会被撤销。
## 2. 六类命令
| 路径后缀 | SDK方法 / 请求类型 | 额外必填字段与结果 |
| --- | --- | --- |
| task-review | ReviewWorkflowTask / ReviewWorkflowTaskRequest | task_id、expected_task_revision字符串、execution_settled=true、outcome=SUCCEEDED或FAILED、非null result;核实本实例任一历史激活的待核查执行 |
| step-resolve | ResolveWorkflowStep / ResolveWorkflowStepRequest | 步骤公共字段、execution_settled=true、outcome=SUCCEEDED或FAILED、result;确认当前叶子步骤的逻辑结论 |
| continue | ContinueWorkflow / ContinueWorkflowRequest | review_resolved=true;确认全部核查事项已处理后解除核查 |
| step-retry | RetryWorkflowStep / RetryWorkflowStepRequest | 步骤公共字段、safe_to_retry=true;为TASK/POLL创建新激活,保留原预算和截止 |
| poll-continue | ContinueWorkflowPoll / ContinueWorkflowPollRequest | 步骤公共字段、pending_confirmed=true;权威结果已确认为PENDING时按原间隔恢复等待,不重查同轮 |
| wait-rearm | RearmWorkflowWait / RearmWorkflowWaitRequest | 步骤公共字段、wait_verified=true;独立SIGNAL/TIMER在原截止内更换等待代次,含首次最多32代 |
所有确认布尔值必须在HTTP中显式提供且为true。拒绝嵌套`Decision`、伪造actor_id、大小写别名和未声明字段。
执行核查请求示例:
```json
{
"expected_revision":"8",
"reason":"已核实请求完成且外部作业仍在处理",
"evidence_ref":"evidence:query-001",
"task_id":"88888888888888888888888888888888",
"expected_task_revision":"4",
"execution_settled":true,
"outcome":"SUCCEEDED",
"result":"PENDING"
}
```
ReviewTask只改变执行结论,旧UNKNOWN尝试和证据保持原样。它产生新的内部结果,必须等待后台消费,当前步骤及实例不会自动解除核查。POLL请求成功不等于流程业务成功;ResolveStep对POLL的成功结果必须映射到固定的业务成功值,不能把PENDING写成步骤成功。TIMER成功只能在首次等待时长满足后确认,result必须为显式null。
PENDING接续请求示例:
```json
{
"expected_revision":"11",
"reason":"沿原间隔继续查询外部作业",
"evidence_ref":"evidence:query-001",
"step_key":"query",
"activation_id":"66666666666666666666666666666666",
"expected_step_revision":"3",
"pending_confirmed":true
}
```
相同字段布局适用于step-resolve、step-retry和wait-rearm,额外字段按上表替换。Continue只有实例公共字段及review_resolved,不要求步骤字段。
## 3. 回执与当前视图
六个方法统一返回WorkflowRecoveryResult;HTTP的data字段为该对象:
| 字段 | 含义 |
| --- | --- |
| instance | 首次管理事务完成时的完整实例快照,字段同[启动回执](workflows.md#2-固定版本启动) |
| audit_id | 本次流程管理审计ID,可用GetWorkflowOperation读取原因、证据及前后摘要 |
| step | 步骤类操作返回当前步骤快照,包含激活代次;不是后续实时状态 |
| task | task-review或step-retry返回执行任务快照;字段同GetTask |
| task_audit_id | task-review对应的独立任务审计ID,与流程审计同事务保存 |
| deduplicated | 是否恢复原回执;恢复原键仍检查当前权限 |
步骤恢复回执示意,省略字段按协议确实不存在,并非JSON占位:
```json
{
"request_id":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"data":{
"instance":{
"id":"22222222222222222222222222222222",
"namespace_id":"33333333333333333333333333333333",
"definition_id":"11111111111111111111111111111111",
"definition_version_id":"44444444444444444444444444444444",
"version":"v1","state":"NEEDS_REVIEW","revision":"13",
"paused":false,"control_revision":"3",
"input":{"n":9007199254740993},"business_key":"operation-001 ",
"deadline_at":"2026-09-18T08:01:00Z",
"created_at":"2026-09-18T08:00:00Z","updated_at":"2026-09-18T08:00:10Z"
},
"audit_id":"99999999999999999999999999999999",
"step":{
"id":"55555555555555555555555555555555","key":"query","kind":"POLL",
"state":"WAITING","revision":"4",
"activation_id":"66666666666666666666666666666666","activation_sequence":1
},
"deduplicated":false
}
}
```
ContinuePoll保留当前激活与信号代次;RetryStep及RearmWait创建新激活。恢复等待或创建新任务后仍须显式Continue解除核查;paused仍为true时还需ControlWorkflow(RESUME)。任何恢复操作都不盲目撤回已发生的外部业务效果。
## 4. SDK接入顺序
以下为嵌入接入方函数的调用片段,api是已认证Client,workflowID为目标实例,operationKey与本次完整命令需要由调用方持久保存:
```go
current, err := api.GetWorkflowStep(ctx, workflowID, "query")
if err != nil { return err }
if current.Step.ActivationID == nil { return errors.New("query is not activated") }
command := orbit.ContinueWorkflowPollRequest{
WorkflowStepDecision: orbit.WorkflowStepDecision{
WorkflowRecoveryDecision: orbit.WorkflowRecoveryDecision{
ExpectedRevision: current.Revision,
Reason: "已核实权威PENDING结果,沿原预算接续",
EvidenceRef: "evidence:query-001",
},
StepKey: current.Step.Key,
ActivationID: *current.Step.ActivationID,
ExpectedStepRevision: current.Step.Revision,
},
PendingConfirmed: true,
}
receipt, err := api.ContinueWorkflowPoll(ctx, workflowID, operationKey, command)
if err != nil { return err } // 不生成新键绕过冲突;结果不明时原命令原键核对。
audit, err := api.GetWorkflowOperation(ctx, workflowID, receipt.AuditID)
if err != nil { return err }
fmt.Println(audit.Action, receipt.Instance.State)
```
完整、可执行的六类SDK场景位于[真实服务集成测试](../../sdk/go/workflow_instances_integration_test.go):UNKNOWN→执行核查→逻辑结论→解除核查;已知失败→剩余预算重试,同时重建信号等待;UNKNOWN查询→核查为PENDING→原间隔接续。运行方式为仓库根目录`make integration`,由脚本创建隔离MySQL、实际服务及凭据。
一般步骤是:查询当前事实 → 提交一个有证据的决定 → 等待该决定产生的内部结果消费 → 重新读取当前版本 → 再提交下一决定。不要自动将任意STATE_CONFLICT重试为“最新版本”;冲突可能意味着新的在途结果、权限变化、原截止已到或预算耗尽,应重新核查。相同命令的响应未知则仍使用原版本和原键。
## 5. 兼容与剩余范围
新路由仅在本开发版本及之后可用;旧服务返回404时不能降级为普通任务重试来绕过Weave所有权。SDK类型独立、版本字段保留uint64精度。规则及数据模型未增加表、字段、外键或级联。
[历史激活/轮次/信号及审计](workflow-history.md)、[实例筛选](workflow-queries.md)、[状态时间线](workflow-events.md)和[任务历史激活来源](task-source.md#5-流程固定来源)均已接入。独立[提交后断线与人工恢复示例](../examples/workflow-recovery.md)提供完整启动、故障注入、三步核查、暂停门控与审计核对。生产数据库切换、容量及恢复目标继续按P6验证,原范围剩余故障见[P4/P5核对](../reports/phase-4-5.md)。