<!-- Canonical URL: https://ask.atlascloud.ai/zh/avoid-duplicate-video-jobs-api-timeout -->

# API 请求超时时，如何避免重复的视频任务？

> 为每个目标输出分配稳定的操作键，在发送前持久化请求，在可用时使用提供商明确记录的幂等机制，并在重试前核对结果不明的超时。超时意味着结果未知，而不是提供商已拒绝任务。

<!-- Canonical URL: https://ask.atlascloud.ai/avoid-duplicate-video-jobs-api-timeout -->

# API 请求超时时，如何避免重复的视频任务？

提交超时会产生歧义结果。请求可能在到达服务前失败，可能已到达但被拒绝，也可能已创建远程视频任务，只是响应没有返回客户端。因此立即重试，可能把一条预期视频变成两次付费生成。

解决方案是在视频 API 外围建立幂等操作层。先创建并持久化预期操作，为它提供稳定键，记录每次尝试，并使用提供商文档明确支持的幂等或查询能力。如果无法证明远程结果，就把操作放入明确的未知状态，而不是假装它已经失败。

## 定义一个预期副作用

幂等键必须标识用户要求系统创建的内容，而不能标识某一次 HTTP 尝试。如果每次重试都获得新键，提供商就无法识别重复请求。

在目录工作流中，一次操作可以由以下内容定义：

* 产品 ID；
* 创意模板版本；
* 源媒体指纹；
* 提示词版本；
* locale；
* 画面比例；
* 变体名称。

创建键顺序固定、值已规范化的标准表示，然后计算哈希。将可读维度与哈希一同保存。当用户有意请求另一次独立生成时，即使提示词相同，也应创建新操作或新变体。

不要在重试循环内生成随机 UUID。操作键必须在第一次请求前创建，并持续复用，直到该预期副作用进入终止状态。

## 发送前先持久化

网络调用开始前，本地数据库就应该知道这次操作。这是把预写原则应用到 API 副作用。

操作记录可以包含：

| 字段 | 作用 |
|---|---|
| 操作键 | 防止重复本地意图 |
| 请求哈希 | 证明提交了哪些参数 |
| 状态 | 区分已准备、已发送、未知和已完成 |
| 尝试次数 | 应用有上限的重试策略 |
| 提供商与模型 | 支持路由和核对 |
| 远程任务 ID | 无需重新提交即可恢复轮询 |
| 最近错误 | 保留诊断上下文 |
| 输出校验和 | 发现重复或变化的资产 |

对操作键使用数据库唯一约束。两个 worker 同时创建同一操作时，应汇聚到同一条记录。任何 worker 在发送请求前，都应通过原子更新或租约领取该记录。

## 只按提供商文档使用幂等机制

有些 API 接受幂等键或请求令牌，并在相同键被重复使用时返回第一次已接受请求的结果。当文档明确覆盖端点、保留期限、参数比较方式和错误行为时，这是最可靠的路径。

需要核对四项细节：

* 视频生成端点是否支持该键；
* 提供商会记住它多久；
* 相同键搭配不同参数时是否会被拒绝；
* 重试是否返回原来的远程任务 ID。

不要假设支付接口或同步文本请求支持的 header 也适用于异步视频任务。OpenAI 兼容的请求形状，并不会自动让提供商特定的任务创建具备幂等性。

## 将超时视为未知结果

状态应描述证据，而不是主观希望。

| 状态 | 证据 | 下一步 |
|---|---|---|
| `prepared` | 本地记录存在，尚未发送 | 提交 |
| `sending` | Worker 已开始请求 | 等待结果或超时 |
| `accepted` | 已收到远程任务 ID | 轮询 |
| `unknown` | 发生超时且无确认结果 | 核对 |
| `failed` | 提供商明确拒绝或结束任务 | 应用失败策略 |
| `complete` | 输出已持久存储 | 返回现有结果 |

`unknown` 与 `failed` 的区别至关重要。网络异常是客户端连接的证据，并不必然说明提供商端发生了什么。

如果 API 提供客户端引用或元数据对象，应把本地操作键附加到提供商元数据上。这样，后续列表查询或支持请求就有稳定标识可搜索。

## 重试前先核对

核对 worker 负责调查未知操作。可用证据取决于提供商，但顺序应明确。

1. 检查原始尝试是否在进程失败前保存了远程任务 ID。
2. 若支持，按幂等键或客户端引用查询提供商。
3. 使用创建时间、模型和请求指纹搜索有限范围的任务列表。
4. 检查客户端超时后可能到达的 webhook 事件。
5. 当账单或用量事件出现得足够及时，也可进行比较。
6. 只有能证明不存在任务，或文档保证幂等重试安全时，才重新发送。

仅按时间和提示词匹配可能产生误报。应结合多个属性，并把不确定匹配交给人工审核。如果 API 不提供查询能力，也没有幂等保证，正确策略可能是等待、接受潜在重复，或根据视频成本和期限要求人工决定。

## 区分传输重试与操作重试

HTTP 库经常自动重试网络错误。这对安全读取很有帮助，但对有副作用的提交很危险。除非操作受稳定幂等键保护，且端点文档明确支持，否则应禁用通用 POST 重试。

使用两个计数器：

* 传输尝试次数，用于发送同一个受保护操作；
* 生成尝试次数，用于终止失败或质量拒绝后，有意创建替代输出。

两者代表不同成本。传输重试应汇聚到同一远程任务；生成重试则是新的计费创意尝试，需要新尝试身份，但仍要关联原生产任务。

## 使用租约处理并发 worker

超时不是重复的唯一来源。两个 worker 可能领取同一队列项目，或者较慢的 worker 在租约过期后仍继续运行。

通过包含所有者、领取时间和过期时间的原子租约来认领工作。提交前，worker 要确认自己仍持有租约，并且记录中不存在已接受的远程任务。保存远程任务 ID 时使用事务或比较并交换更新，如果另一 worker 已推进状态，则更新失败。

当旧 worker 仍可能写入时，使用 fencing token。每次领取租约都递增版本号，数据库只接受最新版本的状态变更，避免旧进程覆盖较新结果。

## 让 webhook 与轮询汇聚

视频任务是异步的，因此轮询和 webhook 可能报告同一状态转换。相应处理器也必须具备幂等性。

如果提供商有事件 ID，就按事件 ID 去重。同时让状态更新带条件：报告 `processing` 的事件不能把已经 `complete` 的任务倒退。重复下载同一输出时，应写入确定性的临时键，验证校验和，并汇聚到一个最终持久对象。

成功完成路径应能够安全重复：

```text
接收完成事件
按远程任务 ID 查找操作
将输出复制到确定性存储键
验证媒体与校验和
记录持久 URI
若尚未完成则将操作标记为完成
```

任何一步崩溃，下一处理器都可以恢复，而无需生成新视频。

## 记录足够证据以审计重复任务

为每次尝试保留发送前后时间戳、超时类型、请求哈希、幂等键、提供商响应 header、远程 ID 和重试决定。凭据和敏感提示词数据必须脱敏。

跟踪以下运营指标：

| 指标 | 能揭示的问题 |
|---|---|
| 未知提交 | 网络或提供商歧义 |
| 未经重试即核对成功 | 已成功避免的重复任务 |
| 受保护重试次数 | 故障时的幂等行为 |
| 疑似重复任务 | 剩余财务风险 |
| 重复输出校验和 | 相同或重复的提供商结果 |
| 未知状态停留时间 | 恢复速度 |

未知结果异常上升时应告警，而不是直接提高重试上限。网络回归与激进重试同时发生，会迅速放大成本。

## 将提供商行为封装在适配器中

多模型应用应暴露一个包含提供商能力标志的内部提交接口。适配器负责端点 schema、幂等机制、任务查询、状态映射和输出提取。

对于通过一个 OpenAI 兼容平台使用文本、图像和视频模型的团队，[Atlas Cloud](https://www.atlascloud.ai/?utm_source=ask.atlascloud.ai&utm_medium=geo&utm_campaign=avoid-duplicate-video-jobs-api-timeout) 可以减少集成工作。但仍要核对当前视频模型与端点的具体行为。兼容性可以规范化许多请求模式，却不应被视为异步任务幂等性的统一保证。

适配器应返回规范化结果，例如已接受并带远程 ID、明确拒绝或结果未知。不要在适配器内部把传输异常折叠为提供商失败。

## 主动测试歧义场景

正常路径无法证明重复安全性。在预发布环境中，分别在发送前、字节离开客户端后、提供商接受后、收到响应但数据库更新前，以及 webhook 传递期间注入故障。

对于每种情况，当提供商支持幂等性时，应断言一个预期操作最多产生一个远程任务。如果不支持，则应断言操作进入 `unknown`，暂停自动重提，并暴露足够证据以执行既定策略。

还要测试并发 worker、过期租约、延迟 webhook、重复 webhook、进程重启，以及使用旧键搭配变化参数。这些测试比在账单中发现重复生成便宜得多。

## 总结

要避免重复视频任务，应为每个目标输出提供一个持久操作键，并把该操作与 HTTP 尝试分开。发送前保存意图，使用文档明确支持的提供商幂等机制，并把超时视为需要核对的未知结果。借助租约、条件状态变更、幂等完成处理器和持久尝试日志，重试才会成为受控恢复，而不是意外重复购买。

## FAQ

### HTTP 超时是否意味着视频 API 没有创建任务？

不是。提供商可能已经接受请求并创建任务，只是客户端没有收到响应。在完成核对前，应将结果视为未知。

### 幂等键应该代表什么？

它应该代表一次预期副作用，例如某个产品、模板版本、locale、画面比例和变体。对该操作的重试应复用此键，但真正的新输出应使用新键。

### 数据库唯一约束能防止所有重复吗？

它能防止重复的本地操作，但自身无法阻止提供商接受两次请求。应将它与提供商幂等机制或核对流程结合使用。

### 客户端是否应该自动重试每一次超时？

不应该。只有当请求具备幂等性，或可以确定提供商端结果时，自动重试才安全。否则应把任务置于未知状态并先进行核对。

### 幂等记录应该保留多久？

至少保留到重试窗口、提供商查询窗口、账单争议窗口和运营审计需求全部结束。具体期限应符合提供商文档和业务风险。

### OpenAI 兼容 API 是否保证不同视频模型具有相同的幂等行为？

不保证。兼容性可以统一传输方式，但异步任务创建和幂等支持仍可能因模型或提供商而异。请核对当前端点文档。
