fix(review): lock OCR backend init, warn on rollback fallthrough, zero-page metric
Address PR #858 review round 2: - OcrProcessor backend resolution is now guarded by an anyio.Lock (lazy-init, double-checked) so a burst of concurrent first-OCR calls resolves the backend once instead of each fetching its own gateway M2M token. - The document_tier1_engine=pymupdf rollback now logs a warning when it falls back to the fast processor (no 'structured' registered) instead of silently using the very engine the operator opted out of. - classify_from_text defaults ocr_frac to 0.0 (not 1.0) for a zero-page PDF, so the recorded classification metric is "fast" (no OCR evidence) rather than a misleading "ocr"; the no_text_layer/bad_text_layer flags are gated on having sampled at least one page. New tests: zero-page classify routes fast, rollback-fallback warning. 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
1634e8adc2
commit
f1272dfe84
@@ -22,6 +22,7 @@ from abc import ABC, abstractmethod
|
||||
from collections.abc import Awaitable, Callable
|
||||
from typing import Any
|
||||
|
||||
import anyio
|
||||
import httpx
|
||||
|
||||
from nextcloud_mcp_server.config import Settings, get_settings
|
||||
@@ -184,6 +185,10 @@ class OcrProcessor(DocumentProcessor):
|
||||
# lifetime is safe.
|
||||
self._backend_resolved = False
|
||||
self._backend: _OcrBackend | None = None
|
||||
# Serialise first-call resolution so a burst of concurrent OCR requests
|
||||
# doesn't each build a backend (and fetch its own M2M token). Lazy-init:
|
||||
# anyio primitives must not be created at import time.
|
||||
self._backend_lock: anyio.Lock | None = None
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
@@ -209,8 +214,12 @@ class OcrProcessor(DocumentProcessor):
|
||||
) -> ProcessingResult:
|
||||
settings = get_settings()
|
||||
if not self._backend_resolved:
|
||||
self._backend = build_ocr_backend(settings)
|
||||
self._backend_resolved = True
|
||||
if self._backend_lock is None:
|
||||
self._backend_lock = anyio.Lock()
|
||||
async with self._backend_lock:
|
||||
if not self._backend_resolved: # double-checked
|
||||
self._backend = build_ocr_backend(settings)
|
||||
self._backend_resolved = True
|
||||
backend = self._backend
|
||||
if backend is None:
|
||||
logger.warning(
|
||||
|
||||
Reference in New Issue
Block a user