OCR:确定性坏输入的 HTTP 500 被归为瞬时错误,重试并计入熔断(parse_layout / recognize_text) #35

Open
opened 2026-10-22 10:41:24 +08:00 by iomgaa · 0 comments
Owner

背景

#34 的设计调研(research-wiki/designs/2026-10-21-issue34-ocr-document-design.md §6)发现,MonkeyOCR 服务对所有确定性的坏输入都返回 HTTP 500,响应体形如 {"detail":"Parsing failed: <原因>"}。2026-10-21 在真实服务上实测:

  • 截断的 PDF:Parsing failed: cannot save with zero pages
  • 伪造 %PDF- 头:Parsing failed: Failed to open stream
  • 乱码当图片:Parsing failed: Failed to open stream
  • 空文件:Parsing failed: Cannot open empty stream
  • 扩展名与内容不符:Parsing failed: is no PDF

服务端 api/main.py:501-503 把一切异常(包括它自己抛的 400)都包成 500 "Parsing failed: ..."。

现状与后果

transports/monkey_ocr.py:96-97 的 _classify_status 对 status >= 500 一律归 TransientError。于是一张损坏的图片会:重试 max_attempts 次、每次计入熔断失败、并喂给选源器失败。

默认配置下熔断的连续失败通道在窗口样本不足(min_calls=10)或失败率 ≥ 0.6 时会开路,有效阈值是 max(配置值, 源并发×2)。低并发配置下,一两张坏图就可能把该 scope 的熔断打开,冷却期内同 scope 的正常调用被 fail_fast 拒绝。

本 issue 要决定的

#34 只在新增的 parse_document 路径上做了窄化(对一组已知的确定性标记改归 RequestRejectedError,保留 status_code=500,熔断记成功不计窗口),既有的 parse_layout / recognize_text 行为没有动,因为这会改变医院线对坏图的重试与熔断行为,属公共行为变更。

需要评估:是否把同样的窄化推广到共享的 _classify_status,以及是否需要一个可配置的标记集合。注意标记是 PyMuPDF 的界面文案,会随服务版本漂移;Parsing failed: 前缀本身不能作为判据(服务会把 Model not initialized 之类的真故障也包成同一前缀)。

需走 brainstorming。

## 背景 #34 的设计调研(research-wiki/designs/2026-10-21-issue34-ocr-document-design.md §6)发现,MonkeyOCR 服务对所有**确定性的坏输入**都返回 HTTP 500,响应体形如 `{"detail":"Parsing failed: <原因>"}`。2026-10-21 在真实服务上实测: - 截断的 PDF:`Parsing failed: cannot save with zero pages` - 伪造 `%PDF-` 头:`Parsing failed: Failed to open stream` - 乱码当图片:`Parsing failed: Failed to open stream` - 空文件:`Parsing failed: Cannot open empty stream` - 扩展名与内容不符:`Parsing failed: is no PDF` 服务端 `api/main.py:501-503` 把一切异常(包括它自己抛的 400)都包成 `500 "Parsing failed: ..."`。 ## 现状与后果 `transports/monkey_ocr.py:96-97` 的 `_classify_status` 对 `status >= 500` 一律归 `TransientError`。于是一张损坏的图片会:重试 `max_attempts` 次、每次计入熔断失败、并喂给选源器失败。 默认配置下熔断的连续失败通道在窗口样本不足(`min_calls=10`)或失败率 ≥ 0.6 时会开路,有效阈值是 `max(配置值, 源并发×2)`。低并发配置下,一两张坏图就可能把该 scope 的熔断打开,冷却期内同 scope 的正常调用被 `fail_fast` 拒绝。 ## 本 issue 要决定的 #34 只在新增的 `parse_document` 路径上做了窄化(对一组已知的确定性标记改归 `RequestRejectedError`,保留 `status_code=500`,熔断记成功不计窗口),**既有的 `parse_layout` / `recognize_text` 行为没有动**,因为这会改变医院线对坏图的重试与熔断行为,属公共行为变更。 需要评估:是否把同样的窄化推广到共享的 `_classify_status`,以及是否需要一个可配置的标记集合。注意标记是 PyMuPDF 的界面文案,会随服务版本漂移;`Parsing failed:` 前缀本身不能作为判据(服务会把 `Model not initialized` 之类的真故障也包成同一前缀)。 需走 brainstorming。
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: iomgaa/PolyGateway#35