test(ingest): cover ocr-incluster routing + fix scan-gate & batch guard
Address claude-review on #922: Blocking — test coverage for the new tier2 rung: - test_registry_tiering.py: inline empty-text routes to ocr-incluster before ocr-upstream; only-incluster-enabled routes to incluster; disabled-incluster skips to upstream; evaluate_escalation empty_text hops to ocr-incluster (and falls through to upstream when incluster off); next_available_tier walks the full fast→structured→ocr-incluster→ocr-upstream ladder + ignore_ocr_enabled ideal-target. - test_escalation_signature.py: enabling document_ocr_incluster_enabled changes the dead-letter signature (independent of the upstream rung). - test_tiered_escalation_strategy.py: structured→ocr-incluster hops to INGEST_QUEUE_OCR_INCLUSTER; tier_for_queue covers the in-cluster queue. Important — real fixes: - registry.py: run scan detection (image_coverage_per_page) when EITHER OCR rung is enabled, not just the upstream one — a tenant with only in-cluster OCR on was missing image-coverage scan signals. - ocr.py: the gateway_only (in-cluster) processor never enters batch mode — the GPU is synchronous/low-latency; batch OCR is the upstream Mistral async path. _get_batch_client short-circuits to None. Covered by a new test. Nit: - cli.py: worker --tier help lists ocr-incluster/ocr-upstream as separate fleets. Left as-is: the lazy anyio.Lock init in OcrProcessor — instances ARE created at module import (document_processors/__init__.py), so deferring lock creation off import time is still required; moving it into __init__ would reintroduce the import-time-primitive issue the comment guards against. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c21804fbbc
commit
87b8edd139
@@ -354,8 +354,9 @@ def worker(concurrency: int | None, tier: str | None):
|
||||
|
||||
\b
|
||||
With --tier the worker drains only that tier's queue (``ingest-<tier>``), so
|
||||
a CPU-bound ``fast`` fleet, an in-cluster ``structured`` fleet, and a paid
|
||||
``ocr`` fleet scale independently. Without it, all tier queues are drained in
|
||||
a CPU-bound ``fast`` fleet, an in-cluster ``structured`` fleet, an on-demand
|
||||
GPU ``ocr-incluster`` fleet, and a paid ``ocr-upstream`` fleet scale
|
||||
independently. Without it, all tier queues are drained in
|
||||
one process (handy for dev / a single Deployment). A low-quality parse hops
|
||||
the job to the next tier's queue automatically (see TieredEscalationStrategy).
|
||||
|
||||
|
||||
@@ -437,7 +437,14 @@ class OcrProcessor(DocumentProcessor):
|
||||
async def _get_batch_client(self) -> "GatewayBatchOcrClient | None":
|
||||
"""Cached gateway batch client (or ``None`` when batch isn't applicable —
|
||||
provider=mistral / no gateway). Resolved once under the backend lock so the
|
||||
token provider's M2M cache survives across documents."""
|
||||
token provider's M2M cache survives across documents.
|
||||
|
||||
The in-cluster (``gateway_only``) rung never uses batch mode: it targets
|
||||
the on-demand GPU, which is synchronous/low-latency, while batch OCR is the
|
||||
upstream (Mistral) async-job path. So even with ``DOCUMENT_OCR_MODE=batch``
|
||||
set globally, the in-cluster tier stays on the synchronous backend."""
|
||||
if self._gateway_only:
|
||||
return None
|
||||
if not self._batch_client_resolved:
|
||||
if self._batch_client_lock is None:
|
||||
self._batch_client_lock = anyio.Lock()
|
||||
|
||||
@@ -458,7 +458,13 @@ class ProcessorRegistry:
|
||||
return None
|
||||
try:
|
||||
image_coverage = None
|
||||
if settings.document_ocr_enabled and settings.document_ocr_detect_scanned:
|
||||
# Scan detection feeds either OCR rung (tier2 in-cluster or tier3
|
||||
# upstream), so run it whenever EITHER is enabled — a tenant with
|
||||
# only in-cluster OCR on still needs image-coverage scan signals.
|
||||
ocr_any_enabled = (
|
||||
settings.document_ocr_enabled or settings.document_ocr_incluster_enabled
|
||||
)
|
||||
if ocr_any_enabled and settings.document_ocr_detect_scanned:
|
||||
try:
|
||||
image_coverage = image_coverage_per_page(content)
|
||||
except Exception:
|
||||
|
||||
Reference in New Issue
Block a user