跳转到内容

工作流错误与重试

只有 script 步骤拥有 retry、on_error,它们不是 if/parallel/循环/workflow 包装通用字段。不能添加 type: retry 或独立 catch 变体。默认只尝试一次然后失败。Args 表达式在脚本尝试循环前求值,重试不能修复该阶段错误。

- id: fetch
script: read_fixture
args: {}
retry:
times: 3
initial_ms: 100
factor: 2.0
max_ms: 5000
jitter: false
on_error: fail

该条目需要现有脚本 read_fixture,不是整份工作流。完整独立用例见下文及 script 步骤。

字段必填、默认与范围
times必填整数 1–10,表示额外重试,总尝试最多 times + 1。
initial_ms必填整数 10–60000。
factor必填有限数 1.0–10.0。
max_ms必填整数,不小于 initial_ms,不大于 60000。
jitter布尔,默认 true。

第 n 次重试前(首次失败后 n=1),基础延迟为 min(initial_ms * factor^(n-1), max_ms),下限 initial_ms。Jitter 乘以 0.75–1.25 均匀随机数并四舍五入毫秒;max_ms 限制的是基础值,不是抖动后的最终值。关闭 jitter 时示例依次等待 100、200、400 ms。Args 只求值一次,各次不变;每次单独记录日志。

可重试运行时类别精确为:queue full、queue wait timeout、script broken、pool spawn failure、timeout、transport。用户 ViatError、普通脚本异常、注释错误、资源缺失/类型不符、environment-not-ready、工作流编排错误都不会自动重试。作为 script failure 的上游 API 拒绝不同于 transport。不按“所有 HTTP 500”这样的文本规则匹配;新错误变体默认不可重试。

等待和尝试共享工作流 deadline。采样退避加 10 ms 余量能放进剩余预算才允许重试,实际 jitter 可再次抽样。因此 times 不是必定执行次数。前次副作用可能已保留,开启重试前先保证写入幂等。

on_error 值最后一次或不可重试失败后的行为
缺失或 fail整个工作流失败;用户拒绝保留 status/code,系统失败标记步骤归属。
continue$step.output 为 null,记录 $step._error 后继续,整个工作流仍可成功。
{catch: [entries...]}执行非空局部恢复分支,成功用最后条目输出替换 owner;恢复失败则工作流失败。Catch 分支内任何层级都不能再嵌 catch。

Continue 错误形状 {code,message,kind,extra?}。用户错误 kind 为 user,保留 code/message/extra,没有独立 status 字段;过载为 overload,超时为 timeout,普通失败为 runtime。$_error 和 $owner._error 仅在 catch 内暴露捕获错误。恢复内部 output/error map 不外泄;catch 成功后不能在外部读取 $owner._error。最后为 parallel 时没有自身值,catch 输出 null。取消绕过 continue/catch,策略不能推翻运维停止请求。

创建 wf_fail:

from viat import ViatError
def main():
raise ViatError(status=409, code="fixture_conflict", message="fixture refusal")

创建 wf_echo:

def main(value):
return value

保存 workflows/recover.yaml:

inputs: {}
steps:
- id: request
script: wf_fail
on_error:
catch:
- id: recovery
script: wf_echo
args:
value:
recovered: true
code: $_error.code
outputs:
result: $request.output
终端窗口
viat script create --name wf_fail --language python --file scripts/wf_fail.py
viat script create --name wf_echo --language python --file scripts/wf_echo.py
viat workflow create recover --file workflows/recover.yaml
viat workflow test recover --input '{}'

预期工作流运行时输出为 {"result":{"recovered":true,"code":"fixture_conflict"}}。1.1.0 CLI 注意:workflow test 只要看到任一失败尝试行,就判为失败,即使 catch/continue 或后续重试已恢复。因此可能只打印失败步骤并 exit 1,不打印成功输出。应在控制台/API 检查工作流最终输出与状态,不能把 CLI 退出判断当作引擎恢复语义。即使加 retry,此用户错误也不会重试。验证 continue 时改为 on_error: continue,outputs 中 result 为 $request.output、code 为 $request._error.code,预期 result null、code fixture_conflict。Catch 外不能引用 recovery。

草稿可有真实副作用,本固定用例刻意没有。一次性项目先移除绑定端点,再删工作流与脚本。被捕获失败的步骤创建的延后 tasks 仍可能在整个工作流恢复成功后提交:延后按整次成功,不是每步事务。不要假定 catch 会回滚工作,必要时显式补偿。限制说明并发失败、取消、重启。