fix(review): close doc via try/finally; don't count parse failures as indexed
Address PR #852 review: - pymupdf.py: the metadata `doc` was only closed on the PdfParseFailed and success paths, so a failure in `_extract_metadata`/`mkdir`/`get_settings` leaked it. `doc` is only needed for metadata + page_count (the heavy parse works from `content` bytes in the worker), so open it, read metadata, and close it immediately under try/finally; drop the two later doc.close() calls. - processor.py: a permanent parse failure early-returned from `_index_document`, after which `process_document` still recorded record_qdrant_operation("upsert", "success") + record_vector_sync_processing(success) -- counting an OOM/timeout bomb as astrolabe_documents_indexed_total{status="success"}. `_index_document` now returns False on that path and the caller skips the success metrics (the failure is already recorded via document_parse_failed_total + the registry's document_parse_total{error}). 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
7db8d3e301
commit
7ec116a3c7
@@ -107,14 +107,19 @@ class PyMuPDFProcessor(DocumentProcessor):
|
||||
if progress_callback:
|
||||
await progress_callback(0, 100, "Opening PDF document")
|
||||
|
||||
# Open document and extract metadata in thread
|
||||
# Open document only to read metadata + page count, then close it
|
||||
# immediately (try/finally so a failure in _extract_metadata can't
|
||||
# leak it). The heavy extraction below works from ``content`` bytes
|
||||
# in the isolated worker, so ``doc`` is not needed past this point.
|
||||
doc = await anyio.to_thread.run_sync( # type: ignore[attr-defined]
|
||||
lambda: pymupdf.open("pdf", content)
|
||||
)
|
||||
|
||||
try:
|
||||
metadata = self._extract_metadata(doc, filename)
|
||||
metadata["file_size"] = len(content)
|
||||
page_count = doc.page_count
|
||||
finally:
|
||||
doc.close()
|
||||
|
||||
if progress_callback:
|
||||
await progress_callback(10, 100, f"Extracting {page_count} pages")
|
||||
@@ -143,7 +148,6 @@ class PyMuPDFProcessor(DocumentProcessor):
|
||||
mem_limit_mb=settings.document_parse_mem_limit_mb,
|
||||
)
|
||||
except PdfParseFailed as exc:
|
||||
doc.close()
|
||||
logger.warning(
|
||||
"Isolated PDF parse failed for %s (reason=%s): %s",
|
||||
filename or "<bytes>",
|
||||
@@ -198,9 +202,6 @@ class PyMuPDFProcessor(DocumentProcessor):
|
||||
metadata["image_paths"] = image_paths
|
||||
metadata["page_boundaries"] = page_boundaries
|
||||
|
||||
# Close document
|
||||
doc.close()
|
||||
|
||||
if progress_callback:
|
||||
await progress_callback(100, 100, "Processing complete")
|
||||
|
||||
|
||||
@@ -237,7 +237,15 @@ async def process_document(
|
||||
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
await _index_document(doc_task, nc_client, qdrant_client)
|
||||
indexed = await _index_document(doc_task, nc_client, qdrant_client)
|
||||
|
||||
# A permanent parse failure returns False: it was already
|
||||
# recorded (document_parse_failed_total + the registry's
|
||||
# document_parse_total{error}) and the placeholder marked
|
||||
# "failed". It is not an indexing event and not retryable, so
|
||||
# don't count it as a successful upsert/indexed document.
|
||||
if indexed is False:
|
||||
return
|
||||
|
||||
# Record successful processing metrics
|
||||
duration = time.time() - start_time
|
||||
@@ -534,8 +542,8 @@ async def _index_document(
|
||||
# on a pathological PDF) returns success=False rather than
|
||||
# raising -- there is nothing to index and retrying would just
|
||||
# fail again. Mark the placeholder "failed" so the scanner stops
|
||||
# re-queuing it (until the file changes) and return without
|
||||
# indexing empty content.
|
||||
# re-queuing it (until the file changes) and return False so the
|
||||
# caller skips the success metrics (it was not indexed).
|
||||
if not result.success:
|
||||
reason = result.metadata.get("parse_failed_reason", "error")
|
||||
record_document_parse_failed(reason)
|
||||
@@ -561,7 +569,7 @@ async def _index_document(
|
||||
doc_task.doc_id,
|
||||
exc_info=True,
|
||||
)
|
||||
return
|
||||
return False
|
||||
|
||||
content = result.text
|
||||
file_metadata = result.metadata
|
||||
|
||||
Reference in New Issue
Block a user