Failure Classification#

本页提供 Perago task attempt 结果状态的精确参考,说明各类失败对应的 Conductor status,以及失败结果是否携带 workspace output。

Perago 的运行时结果只有三个状态:

状态

载荷结构

Conductor 语义

COMPLETED

output required; reasonForIncompletion forbidden

attempt 成功完成。workspace task 已生成 workspace output;workspace-free task 已返回业务 result

FAILED

reasonForIncompletion required; output forbidden

attempt 执行失败,Perago 认为同一 input 自动重试仍可能有意义。

FAILED_WITH_TERMINAL_ERROR

reasonForIncompletion required; output forbidden

attempt 执行失败,Perago 认为同一 input 自动重试没有意义。

RuntimeTaskResult 会拒绝不一致的载荷结构:完成状态必须有 output,失败状态必须有 reasonForIncompletion,失败状态不能携带 output

Classification Rule#

运行时的内部异常 classifier 当前有这些规则:

异常类型

Result status

说明

PreGuardrailViolation

FAILED_WITH_TERMINAL_ERROR

task body 尚未运行,输入 workspace 未满足 task 的 pre guardrail。

TaskTerminalError

FAILED_WITH_TERMINAL_ERROR

任务函数显式声明同一 input 自动重试没有意义。

TaskFailed

FAILED

任务函数显式声明该 attempt 失败,但同一 input 稍后重跑可能成功。

其他异常

FAILED

包括 bad input、Pydantic 校验失败、未知业务异常、post guardrail、attempt fence、publish fence 和 LakeFS 操作失败。

任务作者应使用显式 failure API 表达业务执行失败:

  • raise TaskFailed("...") 表示可自动恢复、值得重试的执行失败。

  • raise TaskTerminalError("...") 表示同一 input 自动重试没有意义的执行失败。

  • 未知、未处理的普通异常仍映射为 FAILED,让 Conductor 按 retry policy 处理。

业务可恢复但不应自动重试的情况不使用 Conductor failed 机制。业务函数应返回成功的 Result Output,例如 status="REJECTED"status="NEEDS_ACTION",再由 WorkflowDef 的分支逻辑处理。

Workspace Task Attempt#

Workspace task 的 attempt 生命周期中,失败分类如下。

阶段

典型原因

Result status

是否发布 workspace output

input validation

input 顶层字段缺少 workspaceparamsWorkspaceInput 无效;params 额外字段或类型错误

FAILED

download

LakeFS repository/ref 不存在、连接失败、本机 workspace 写入失败

FAILED

pre guardrails

输入 workspace 缺少必需文件/目录/glob,或命中 forbidden glob

FAILED_WITH_TERMINAL_ERROR

task body retryable failure

用户函数抛出普通异常、TaskFailed,或返回值不能通过 output Pydantic model 校验

FAILED

task body terminal failure

用户函数抛出 TaskTerminalError,表示可检测且不可重试的执行前提错误

FAILED_WITH_TERMINAL_ERROR

task body business branch

用户函数成功判定业务无法继续自动执行,但 workflow 可处理该分支

COMPLETED

视 workspace access mode 而定

post guardrails

输出 workspace 文件未通过 task 的 post guardrail

FAILED

read-only completion

WorkspaceSpec(read_only=True) 的 task 成功完成

COMPLETED

否,output ref 保持 input ref

no-op writable completion

read_only=False 且 workspace diff 为空,target HEAD 状态可解释

COMPLETED

否,output ref 保持 input ref

first attempt fence

task body 后、stage 前发现 Conductor attempt 已不再是当前 attempt

FAILED

stage

workspace 含 symlink、上传/删除/commit 失败

FAILED

second attempt fence

stage 后、publish 前发现 attempt 已失效

FAILED

publish fence / merge

target branch 被无关提交推进、merge 失败或 merge timeout

FAILED

staging cleanup

staging branch 删除失败

保留原始 result

保留原始 result

local cleanup

attempt-local workspace 删除失败

保留原始 result

保留原始 result

Workspace task 在 body 成功、post guardrail 通过后,按 workspace access mode 和 diff 决定完成路径。read_only=True 不进入 LakeFS HEAD 检查或 publication;read_only=False 且 diff 为空时 Perago 不会创建 empty commit,但必须通过 no-op HEAD 状态检查;read_only=False 且 diff 非空时必须完成 stage 和 publish。完成 output 会包含 workspaceresult;失败 output 不会带 workspace,也不会把未发布的 attempt-local workspace 暴露给下游。

Workspace-Free Task Attempt#

Workspace-free task 不下载、不发布 workspace,也没有 guardrail 或 publish fence。

阶段

典型原因

Result status

input validation

input 顶层字段缺少 paramsparams 额外字段或类型错误

FAILED

task body retryable failure

用户函数抛出普通异常或 TaskFailed

FAILED

task body terminal failure

用户函数抛出 TaskTerminalError

FAILED_WITH_TERMINAL_ERROR

task body business branch

用户函数成功判定业务无法继续自动执行,但 workflow 可处理该分支

COMPLETED

result validation

返回值不能通过 output Pydantic model 校验

FAILED

success

业务函数返回值通过 output model 校验

COMPLETED

Workspace-free task 的 COMPLETED output 只包含 result。它不会生成 workspace output,也不能通过 TaskControls.publish_budget 配置发布预算。

Conductor Result Payload#

Perago 内部先构造 RuntimeTaskResult,再转换成 Conductor SDK 的 TaskResult

COMPLETED 会写入:

{
  "status": "COMPLETED",
  "output": {
    "result": {
      "valid": true
    }
  }
}

FAILED 会写入:

{
  "status": "FAILED",
  "reasonForIncompletion": "workspace task input must contain only workspace and params"
}

FAILED_WITH_TERMINAL_ERROR 会写入:

{
  "status": "FAILED_WITH_TERMINAL_ERROR",
  "reasonForIncompletion": "pre guardrail require_glob('raw/**/*.parquet') matched 0 files; min_count=1"
}

worker_id 不属于 RuntimeTaskResult payload。worker 向 Conductor 回写结果时会把 worker_id 写入 SDK TaskResult 字段,用于从 Conductor attempt 反查本机 worker 日志目录。

Recovery Boundary#

Perago 的失败分类是 fail-closed 的:

  • publish fence、stale attempt 和 LakeFS merge 错误不会被包装成成功。

  • 业务可恢复分支不会被包装成 Conductor failure;它们应作为成功的 Result Output 交给 workflow 分支处理。

  • staging cleanup 和 local cleanup 的错误只写日志,不覆盖原始 task result。

  • publish timeout 或 result update 失败后,不应直接假设 publish 没发生;下一次 retry 按 LakeFS 发布协议 检查 target HEAD 状态。

MVP 不提供严格 exactly-once publication 证明。Reference 中的失败分类只描述 worker 如何回写当前 attempt result;跨 attempt 的发布判断来自 Conductor attempt fence 和 LakeFS HEAD 状态。