docs: 路径差异改为链回总表,不再各页复述
参考-异常 与 解释-错误四分类 里「按 Retry-After 等待只在 chat 路径」的复述 是错的(backoff_delay 三路共用,EMBED 也认;只有 OCR 的 transport 不解析该 头)——第六轮修了总表却漏了这两处复述,正是「复述而非链接」的代价。两处改为 指向 解释-治理行为 的适用性总表。
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
| 异常 | 触发 | 库内治理行为 |
|
||||
|---|---|---|
|
||||
| `TransientError` | 超时 / 5xx / 网络抖动 / SSE 截断 / 429 / **空补全**(200 且流程完整但 content 空白)/ 响应体非法 JSON 或缺 choices | 换源重试 + 退避。429 pushback(按 Retry-After 等待、不耗重试预算)**只在 chat 路径**;`EmbeddingClient`/`OcrClient` 的 429 照常计入 `MAX_ATTEMPTS` |
|
||||
| `TransientError` | 超时 / 5xx / 网络抖动 / SSE 截断 / 429 / **空补全**(200 且流程完整但 content 空白)/ 响应体非法 JSON 或缺 choices | 换源重试 + 退避。429 的 pushback 待遇**三条路径不同**(不耗重试预算是 chat 独有,按 Retry-After 等待是 chat + EMBED 有、OCR 无),逐项见 [[解释-治理行为]] 的适用性总表 |
|
||||
| `SourceDeadError` | 401 / 403 / 429+insufficient_quota(欠费) | 立即熔断该源 + 换源 |
|
||||
| `RequestRejectedError` | **400 及其余未特判的非 200 状态码**(402/404/408/409/422…) / 内容拒绝 / **OCR 的 200 但 `success≠true`**(`status_code=200`) | 不重试不换源,直接抛给业务。base_url 配错导致的 404、上游用 402 表达欠费都走这里立即终态,`exc.status_code` 携原状态码 |
|
||||
| `ResultInvalidError` | 调用成功但结果不合格(坏 JSON / 维度不符 / 退化 bbox) | **不熔断**;结构化场景先有界重问,仍失败才抛 |
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
## 几个边界裁决(容易搞错的)
|
||||
|
||||
- **429 归 Transient 但特殊**:它是上游的"慢点"信号(pushback),不计入熔断失败率(三条路径通用)——否则高峰期会把健康源全熔掉。但"**不消耗重试预算、按 Retry-After 等待、靠调用级 stall 判死**"这套**只在 chat 路径生效**;`EmbeddingClient` / `OcrClient` 的治理循环对 429 照常 `fails += 1` 计入 `MAX_ATTEMPTS`,耗尽后的失败原因是 `retry_exhausted` 而非 `stalled`。
|
||||
- **429 归 Transient 但特殊**:它是上游的"慢点"信号(pushback),不计入熔断失败率——这一条三路径通用,否则高峰期会把健康源全熔掉。但 pushback 的其余待遇(不耗重试预算、按 Retry-After 等待、靠调用级 stall 判死)**按路径而异**,逐项对照见 [[解释-治理行为]] 的适用性总表,本页不复述。
|
||||
- **429 + insufficient_quota 归 SourceDead**:欠费不是限流,等多久都没用。
|
||||
- **HTTP 响应本身证明服务活着**:即使是业务层面的失败响应(如 OCR 返回 success=false),熔断记账也算成功——熔断度量的是"服务是否可达",不是"结果是否满意"。
|
||||
- **SSE 截断(收到内容但缺 [DONE])归 Transient** 且不写缓存——把半截响应当成功缓存住是前身项目的真实事故。**这条只在默认 `MISSING_DONE=retry` 下成立**:配成 `salvage` 时,有内容的截断会被打捞成正常响应返回**并照常写入缓存**——只有在截断前已收到 usage 帧时才标 `usage_source=estimated`,而库强制 `include_usage`、usage 帧紧邻 `[DONE]`,所以**常态是标 `unavailable`、tokens=0、cost=NULL**,打捞响应无法只靠 `usage_source` 识别,整个 TTL 内被复用——正是这句声称已防住的那起事故。零内容断流(early_eof)无论怎么配都是 Transient。
|
||||
|
||||
Reference in New Issue
Block a user