开始
↓
【for 循环】重试次数 ≤ 最大重试次数
↓
是否有已锁定的通道(lockedCh)?
├─ 是 → 使用该锁定通道
│ ↓
│ 是否是第1次以上重试?
│ ├─ 是 → 执行 SetupContextForSelectedChannel
│ │ ↓
│ │ Setup 是否失败?
│ │ ├─ 是 → 封装错误 → break 退出循环
│ │ └─ 否 → 继续
│ └─ 否 → 跳过 Setup
└─ 否 → 调用 getChannel 获取通道
↓
获取通道是否失败?
├─ 是 → 记录日志 → 封装错误 → break
└─ 否 → 继续
↓
addUsedChannel(记录使用通道)
↓
获取 bodyStorage
↓
获取 body 是否失败?
├─ 是 → 封装对应错误 → break
└─ 否 → 重置 Request.Body
↓
执行 relay.RelayTaskSubmit 提交任务
↓
任务是否成功(taskErr == nil)?
├─ 是 → break 退出循环(成功结束)
└─ 否 → 继续处理错误
↓
是否非本地错误?
├─ 是 → 执行 processChannelError
└─ 否 → 跳过
↓
判断是否需要继续重试(shouldRetryTaskRelay)
├─ 是 → retry++ → 回到循环开头
└─ 否 → break 退出循环
↓
结束
逐行逻辑拆解(从上到下顺序判断,命中即终止后续判断)
if openaiErr == nil { return false }
没有错误、请求正常返回,不重试。
if service.ShouldSkipRetryAfterChannelAffinityFailure(c) { return false }
开启了通道亲和锁定(成功后切换亲和关闭),上一个通道失败后固定不再换渠道,不重试。
if types.IsChannelError(openaiErr) { return true }
底层通道故障(网络超时、服务商连接失败、服务宕机等),强制重试。
if types.IsSkipRetryError(openaiErr) { return false }
业务类不可重试错误(参数错误、模型不存在、权限不足等),不重试。
if retryTimes <= 0 { return false }
剩余可重试次数用尽,不重试。
if _, ok := c.Get("specific_channel_id"); ok { return false }
本次请求手动指定了单一固定通道,不允许自动换服务商,不重试。
if code >= 200 && code < 300 { return false }
HTTP 2xx 成功状态码,业务正常,不重试。
if code < 100 || code > 599 { return true }
状态码不在 HTTP 标准区间,属于底层协议异常,强制重试。
if operation_setting.IsAlwaysSkipRetryCode(openaiErr.GetErrorCode()) { return false }
错误码在后台配置的「禁止重试黑名单」,不重试。
return operation_setting.ShouldRetryByStatusCode(code)
最终依据后台自定义配置:当前 HTTP 状态码是否允许重试。