# 重新运行算子

从已有工作流作业的指定算子重新运行工作流。重新运行算子会创建新的分支和工作流作业；它不会修改原工作流作业，也不能自动撤销该算子此前产生的外部副作用。

## 前提条件

- 已保存工作流 ID 和源工作流作业 ID。
- 已从工作流作业结果的 `node_states` 或算子详情中取得算子键 `node_key`。
- 源工作流作业已处于允许规划重新运行的状态。

重新运行前必须先获取重新运行计划。计划会告诉你可用模式、源算子运行、受影响的下游算子和当前契约哈希；不要直接猜测请求参数。

## 相关接口

| 方法与路径 | 用途 |
| --- | --- |
| `GET /workflow/v2/workflow-apps/{workflow_id}/executions/{execution_id}/nodes/{node_key}/rerun-plan` | 计算当前算子的重新运行计划。 |
| `POST /workflow/v2/workflow-apps/{workflow_id}/executions/{execution_id}/nodes/{node_key}/reruns` | 按已确认计划创建重新运行。 |
| `GET /workflow/v2/workflow-apps/{workflow_id}/executions/{execution_id}/reruns/{rerun_id}` | 查询重新运行状态。 |
| `POST /workflow/v2/workflow-apps/{workflow_id}/executions/{execution_id}/reruns/{rerun_id}/cancel` | 请求取消重新运行。 |

## 1. 获取重新运行计划

```bash
curl --get \
  "$PRODUCT_API_BASE_URL/workflow/v2/workflow-apps/$WORKFLOW_ID/executions/$EXECUTION_ID/nodes/$NODE_KEY/rerun-plan" \
  -H "X-API-Key: $PRODUCT_API_KEY" \
  -H "X-Workspace-ID: $WORKSPACE_ID" \
  -H "Accept: application/json"
```

如果一个算子存在多个历史运行候选，可以通过查询参数 `source_node_execution_id` 指定候选；其值应来自算子详情或前一次计划响应。

成功响应的计划位于 `data.plan`：

```json
{
  "code": "OK",
  "msg": "OK",
  "data": {
    "plan": {
      "workflow_id": "<WORKFLOW_ID>",
      "source_execution_id": "<EXECUTION_ID>",
      "node_key": "<NODE_KEY>",
      "source_node_execution_id": "<SOURCE_NODE_EXECUTION_ID>",
      "rerun_contract_hash": "<RERUN_CONTRACT_HASH>",
      "available_modes": ["continue_from_node"],
      "affected_downstream_nodes": [],
      "validation": {
        "ok": true
      }
    }
  }
}
```

只有 `validation.ok` 为 `true` 时才进入下一步。向用户展示 `affected_downstream_nodes`，并检查目标算子及下游算子是否会重复写入文件、数据库、通道或外部服务。

## 2. 创建重新运行

请求必须使用同一计划返回的模式、源算子运行 ID 和契约哈希：

```bash
curl -X POST \
  "$PRODUCT_API_BASE_URL/workflow/v2/workflow-apps/$WORKFLOW_ID/executions/$EXECUTION_ID/nodes/$NODE_KEY/reruns" \
  -H "X-API-Key: $PRODUCT_API_KEY" \
  -H "X-Workspace-ID: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "continue_from_node",
    "source_node_execution_id": "<SOURCE_NODE_EXECUTION_ID>",
    "expected_rerun_contract_hash": "<RERUN_CONTRACT_HASH>",
    "reason": "Retry after checking the failed node"
  }'
```

| 字段 | 类型 | 必需 | 说明 |
| --- | --- | --- | --- |
| `mode` | string | 是 | 重新运行模式。必须来自当前计划的 `available_modes`。 |
| `source_node_execution_id` | string | 是 | 作为重新运行起点的算子运行 ID。 |
| `expected_rerun_contract_hash` | string | 是 | 当前重新运行契约哈希，用于防止计划读取后工作流或工作流作业上下文已经变化。 |
| `values` | object | 否 | 运行输入覆盖。只有所选模式和计划允许时使用。 |
| `config_override` | object | 否 | 算子配置覆盖。字段应符合计划返回的可覆盖配置 Schema。 |
| `reason` | string | 否 | 本次重新运行的原因，便于审计和排查。 |

若契约哈希已经变化，重新读取计划并再次确认影响范围，不要绕过冲突重复提交。

## 3. 查询重新运行状态

创建成功后，重新运行信息位于 `data.rerun`。保存 `rerun_id` 和 `new_workflow_execution_id`：

```json
{
  "code": "OK",
  "msg": "OK",
  "data": {
    "rerun": {
      "rerun_id": "<RERUN_ID>",
      "branch_id": "<BRANCH_ID>",
      "new_workflow_execution_id": "<NEW_EXECUTION_ID>",
      "source_execution_id": "<EXECUTION_ID>",
      "node_key": "<NODE_KEY>",
      "mode": "continue_from_node",
      "status": "<STATUS>"
    }
  }
}
```

使用重新运行详情接口查询分支状态；需要完整工作流输出时，使用新的工作流作业 ID 调用结果接口。不要把源工作流作业的旧结果当作新分支结果。

## 常见问题

| 现象 | 先检查 | 下一步 |
| --- | --- | --- |
| 计划校验不通过 | `validation.code`、`message` 和 `reasons` | 修复计划指出的问题，不直接创建重新运行。 |
| 契约哈希冲突 | 工作流版本和最新计划 | 重新获取计划并让用户再次确认影响范围。 |
| 算子存在多个候选 | `candidates` | 选择正确的 `source_node_execution_id` 后重新获取计划。 |
| 重新运行完成但读取到旧结果 | 新工作流作业 ID | 使用 `new_workflow_execution_id` 查询状态和结果。 |

## 下一步

- [运行、查询与取消](run-query-cancel.md)
- [工作流产物、数据血缘与版本切换](artifacts-lineage-version-switching.md)
