阅读文本 / Reading text
本文使用合成样本演示处理方法。代码已通过隔离环境中的示例检查;这不代表对所有真实文件或产品效果的保证。处理重要文件前,请保留原件,并按文中的边界与验收项复核。
报错后再试一次很常见,报错后无限再试就会把小故障放大。权限错误、账户欠费、损坏文件和服务临时繁忙不应该走同一条重试路径。分类之后,再决定等待多久、最多试几次,以及是否需要用户介入。
先判断重试会不会产生重复任务
POST 超时最棘手:客户端没收到响应,不代表服务端没有创建任务。没有幂等键或任务查询机制时,盲目重发可能创建多个翻译任务。重试策略应优先服从接口契约,而不是只看 HTTP 状态码。
把次数和等待预算写成纯函数
from enum import Enum
class Failure(Enum):
TRANSIENT = "transient"
AUTH = "auth"
BILLING = "billing"
INVALID_INPUT = "invalid_input"
def delay_for(kind, attempt, replay_safe):
if type(attempt) is not int or attempt < 0:
raise ValueError("invalid attempt")
if not replay_safe or kind is not Failure.TRANSIENT:
return None
schedule = (1, 2, 4)
return schedule[attempt] if attempt < len(schedule) else None
assert delay_for(Failure.TRANSIENT, 0, True) == 1
assert delay_for(Failure.TRANSIENT, 2, True) == 4
assert delay_for(Failure.TRANSIENT, 3, True) is None
assert delay_for(Failure.TRANSIENT, 0, False) is None
assert delay_for(Failure.BILLING, 0, True) is None
assert delay_for(Failure.INVALID_INPUT, 0, True) is None
代码只计算计划,不实际等待或发请求。固定的一、二、四秒是合成演示,不是通用服务建议。生产还要考虑服务端
Retry-After
、随机抖动、整体截止时间和并发限制;若服务端要求等待超过本地预算,应停止而不是提前重试。
错误类型对应不同动作
失败
可选动作
不应默认做
临时拥塞
有界退避
所有任务同时密集重发
登录或权限失效
明确提示重新授权
不断重复旧凭据
账户或账单异常
停止并报告
自动充值或换账户
输入结构错误
让用户修复输入
重发完全相同文件
保存逻辑任务与尝试记录
一次用户操作对应一个逻辑任务,下面可以有多个尝试。每次尝试记录开始时间、失败类别和远端任务 ID,最终只选择一份经过验收的结果。这样既能排查重试,也不会把尝试数误算成用户请求数。
翻译体验的稳定来自解释清楚
对接
OmniDoc(产品入口)
时,前端应该明确显示等待、需要重新授权或需要检查账户,而不是把所有情况变成“生成中”。用户愿意等待一个有状态、有出口的任务,不愿意反复点击一个没有反馈的按钮。
参考:
Python enum
。
- 1 -
更新于 2026-10-08