refactor(ingest): doc legacy ocr queue; fix docstrings + getattr guard

Address claude-review round 2 on #922:

- Legacy `ingest-ocr` tier resolution (important 1): document why it deliberately
  resolves to `fast` rather than mapping to `ocr-upstream` — stranded pre-split
  jobs re-extract empty and re-escalate via the ladder to the cheap
  `ocr-incluster` rung, keeping them OFF the paid upstream rung. Added a
  tier_for_queue(LEGACY_INGEST_QUEUE_OCR) == "fast" assertion.
- Double get_settings() in `_get_batch_client` (important 2): bind once to a local.
- Stale docstrings (important 3): OcrProcessor (serves both rungs now),
  _tier_available (both OCR rungs gated), evaluate_escalation (targets
  ocr-incluster, falls through to ocr-upstream).
- Misconfigured model_setting (nit 5): OcrProcessor.__init__ raises ValueError on
  an unknown settings attr (fail-fast at startup vs AttributeError mid-OCR); also
  removes the dynamic-getattr static-analysis smell SonarCloud flagged.
- Redundant guard (nit 4): kept `and ocr_tier is not None` — it's required for ty
  to narrow ocr_tier to str for record_document_escalation; added a comment.
- Test gap (nit 6): added a test pinning the CURRENT incluster-failure ->
  tier-1 fallback (does NOT cascade to upstream) so the future 503-escalation
  change is an explicit diff.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-06-18 00:16:20 +02:00
co-authored by Claude Opus 4.8
parent 87b8edd139
commit 6e32bd9561
5 changed files with 55 additions and 8 deletions
@@ -119,6 +119,15 @@ def tier_for_queue(queue: str | None) -> str:
The queue-aware task uses this to pick which single tier to parse with: the
job's current queue *is* its tier. A job on the legacy ``ingest`` queue (or
any unrecognised queue) defaults to the cheapest tier.
The pre-split legacy OCR queue ``ingest-ocr`` (``LEGACY_INGEST_QUEUE_OCR``)
is deliberately NOT mapped here, so it also resolves to ``fast``. These are
in-flight jobs enqueued before the tier2/tier3 split; running them at fast
re-extracts (an empty layer for a scanned doc), which re-enters the ladder
and naturally re-escalates to ``ocr-incluster`` (the cheap GPU rung) — one
extra cheap hop, but it keeps stranded legacy OCR jobs OFF the paid upstream
rung rather than mapping them straight to ``ocr-upstream``. The set is
transient (only during a single rollout window).
"""
return _QUEUE_TIERS.get(queue or "", "fast")