fix(canonical): marker_worker transport 계층 오류는 transient retry 분류

기존: (ConnectError, TimeoutException) 만 transient → raise → queue retry.
ReadError / WriteError / RemoteProtocolError 같은 다른 transport 류는
'except Exception' 이 잡아 _fail 처리 → max_attempts 무시하고 final fail.

Phase 1D pilot 에서 5111/5115 두 건이 'Server disconnected without
sending a response' (RemoteProtocolError) 로 retry 없이 final fail.

Fix: except (ConnectError, TimeoutException) → except TransportError.
TransportError 가 Connect/Read/Write/RemoteProtocol/Timeout 의 공통 부모
라서 모든 transport 계층 오류가 transient queue retry 대상이 됨.

5135 의 ReadTimeout (queue exhausted) 는 본 fix 와 별개 — 8.4MB PDF 가
MARKER_TIMEOUT=300s 안에 못 끝나 3번 retry 다 timeout. timeout 자체를
늘리거나 큰 PDF 분할 처리하는 별도 결정 필요.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-05-03 15:29:46 +09:00
parent 5185501bbd
commit 5b62c59f8a
+7 -2
View File
@@ -167,8 +167,13 @@ async def process(document_id: int, session: AsyncSession) -> None:
return
logger.exception(f"[marker] http error id={document_id}: {exc}")
raise
except (httpx.ConnectError, httpx.TimeoutException) as exc:
logger.warning(f"[marker] transient error id={document_id}: {exc}")
except httpx.TransportError as exc:
# transport 계층 오류 — Connect/Read/Write/RemoteProtocol/Timeout 류 전부 transient.
# marker-service 응답끊김(RemoteProtocolError) / 모델 워밍업 / 큰 PDF I/O 끊김 등에서 발생.
# queue retry 대상 (max_attempts 까지 자동 재시도).
logger.warning(
f"[marker] transient error id={document_id} kind={type(exc).__name__}: {exc}"
)
raise
except Exception as exc:
logger.exception(f"[marker] unexpected error id={document_id}: {exc}")