polish(mail): consistency guards (PR #935 round-7)

Non-blocking consistency fixes:
- scanner.py: skip re-queuing a mail_message whose placeholder status is
  "failed" (mirrors the file scanner's permanent-failure guard); the
  modified_at branch still retries once the message changes.
- search/context.py: return None on an empty get_message payload during context
  expansion, mirroring the processor's index-time empty-payload guard.
- tests: cover the non-numeric mailbox_id fail-open branch in the verifier.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-06-20 13:44:28 +02:00
co-authored by Claude Opus 4.8
parent 10e768e414
commit 15042c1b1b
3 changed files with 30 additions and 0 deletions
+4
View File
@@ -834,6 +834,10 @@ async def _fetch_document_text(
# Reconstruct full content via the shared helper so chunk offsets
# match what the processor indexed (single source of truth).
message = await nc_client.mail.get_message(int(doc_id))
# Empty payload (OCS data=null with a <400 meta) -> skip context
# expansion, mirroring the processor's index-time guard.
if not message:
return None
return build_mail_content(message)
else:
logger.warning("Unsupported doc_type for context expansion: %s", doc_type)
+10
View File
@@ -1549,6 +1549,16 @@ async def scan_mail_messages(
needs_indexing = True
elif existing_metadata.get("modified_at", 0) < modified_at:
needs_indexing = True
elif existing_metadata.get("status") == "failed":
# A permanent processing failure — don't re-queue an
# unchanged message that will just fail again; the
# modified_at branch above retries once it changes
# (mirrors the file scanner's failed-placeholder guard).
logger.debug(
"Skipping mail message %s: previous processing "
"failed permanently",
doc_id,
)
elif existing_metadata.get("is_placeholder", False):
queued_at = existing_metadata.get("queued_at", 0)
placeholder_age = time.time() - queued_at