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

86 lines
5.4 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.
# 有界轮询:请求重试与业务轮次分别计数
[完整源码](../../sdk/go/examples/workflow-poll/main.go)通过公共SDK发布POLL定义,启动真实Worker,并请求一个本机HTTP渠道夹具。流程先由TASK向本机渠道提交一次作业,受理回执提供固定operation_id,随后POLL只查询这个作业;平台没有集成任何具体业务渠道。
同一命令依次运行两个流程:
| 场景 | 渠道响应 | 平台结果 |
| --- | --- | --- |
| success | 提交一次;首次查询503,重试PENDING,下一轮DONE | 2个业务轮、3次查询尝试,SUCCEEDED |
| exhausted | 提交一次;两次查询都成功返回PENDING | 2个业务轮、2次查询尝试,NEEDS_REVIEW |
## 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 poll-example --namespace default --environment development \
--queue workflows --workflow-access --workflow-run-access --worker-access \
--output .local/poll.credentials.json
go run ./cmd/orbit
```
bootstrap只执行一次,凭据文件存在时不会覆盖。另开终端,从仓库根目录运行:
```sh
cd sdk/go
ORBIT_URL=http://127.0.0.1:8080 \
ORBIT_CREDENTIALS_FILE=../../.local/poll.credentials.json \
go run ./examples/workflow-poll
```
程序自行创建并关闭本机HTTP夹具,不需要启动第三方系统,不向公网提交操作。正式接入使用HTTPS/WSS和分角色凭据,将只读查询处理器替换为自己的渠道调用。
## 2. 定义与调用链
CreateWorkflowDefinition → PublishWorkflowVersion(v1) → StartWorkflow → 自动Worker提交一次 → 按受理回执中的身份查询 → GetWorkflow/GetWorkflowStep → ListWorkflowPollRounds → GetTaskSource/ListTaskAttempts → Worker排空。
输入为`{"operation_id":"本次示例的固定操作身份"}`。submit任务只允许一次尝试并使用RECONCILE_ONLY,提交结果未知时必须核查;query通过WorkflowRef("submit")引用已保存受理回执,每轮及同轮重试保持这个身份。结果契约是STRING枚举PENDING/DONE。定义中设置:
```go
poll := orbit.WorkflowPoll{
Task: orbit.WorkflowTask{
// 处理器、输入/输出契约和队列等完整字段见可运行源码。
Retry: orbit.RetryPolicy{
MaxAttempts: 2, InitialDelayMS: 1000,
MaxDelayMS: 1000, AttemptTimeoutMS: 5000,
},
TimeoutMS: 20000,
RecoverySafety: orbit.RecoveryIdempotent,
},
MaxRounds: 2, TimeoutMS: 30000, IntervalMS: 1000,
Pending: []string{"PENDING"}, Succeeded: []string{"DONE"},
}
```
本片段说明预算配置,不是可单独发布的完整定义;源码包含所有必填字段。流程总时限45秒,查询总时限30秒,轮次包含首次;实际任务还受流程及节点原截止限制。
受控渠道的503表示明确拒绝只读查询,因此返回`WorkerFailure{Code:"QUERY_TEMPORARY", Retryable:true}`。传输错误仍返回普通error,保留未知结果,由冻结的安全策略决定后续。只有明确知道请求失败才可声明WorkerFailure,不能把任意网络超时归类为明确失败。
HTTP 200的PENDING直接作为成功结果返回给Orbit,不由Worker自己循环或sleep。Weave保存轮间等待、释放Worker槽位,并在原间隔后创建下一轮任务。轮次耗尽不假定外部作业失败,也不重置预算或再次提交外部作业。
## 3. 预期输出及验证
前面的scenario、operation、workflow字段每次不同。两个最终结果为:
```text
poll_scenario=success state=SUCCEEDED submissions=1 rounds=2 attempts=3 requests=3 deadline_preserved=true worker_drained=true
poll_scenario=exhausted state=NEEDS_REVIEW submissions=1 rounds=2 attempts=2 requests=2 deadline_preserved=true worker_drained=true
```
程序从实际历史读取两轮,每页1条;成功场景第一轮包含FAILED和SUCCEEDED两次尝试,第二轮只有一次SUCCEEDED。耗尽场景两轮请求都成功,逻辑步骤仍进入核查,没有current_task_id或next_poll_at继续运行。每轮任务来源必须指向原实例与轮次,原查询/实例截止保持不变,每个流程只有一次POST提交;Worker实际执行与确认总数包含该提交,所以成功场景共4次、耗尽场景共3次,其中查询请求分别为3次和2次。
## 4. 失败、重跑与清理
程序总运行期限60秒,每个Worker排空期限5秒。发生意外状态、权限错误、响应损坏或预算不符会非零退出,不自动换版本、续期或解除核查。
每次重新运行会创建新的独立示例身份,不代表对上一次未知响应的恢复。生产调用方应持久保存幂等键及完整命令;响应不明时原命令原键核对,不能重新执行此示例来替代恢复。
正常结束关闭本机渠道与Worker,保留两个流程和所有历史,其中exhausted流程有意保留NEEDS_REVIEW供查看。不要将该示例放进生产定时任务无限创建待核查记录。真实渠道状态和证据需由接入方核实,再通过[人工恢复API](../api/workflow-recovery.md)决定后续;示例不会伪造最终成功。
回归入口是`make integration`。SDK预算与字段见[定义格式](../api/workflow-definition-format.md),原截止与查询语义见[时钟约定](../13-workflow-clock.md),阶段证据见[P4/P5核对](../reports/phase-4-5.md)。