refactor(documents): fully decouple document stack from server startup; Windows-safe tests

Addresses round-1 review on #878:

- Move the eager `document_processors` imports out of the API startup graph:
  `app.py` (get_registry now imported inside initialize_document_processors,
  after the disabled early-return) and `vector/processor.py` (get_registry now
  imported at its single use site). Importing `app` + `cli` no longer loads
  `document_processors` / `_isolation` at all -- the #877 stack is fully out of
  startup (pymupdf still loads via search/pdf_highlighter, a Windows-compatible
  and separately-tracked concern).
- Make `tests/unit/test_pdf_parse_isolation.py` importable on Windows: guard the
  top-level `import resource` with try/except and skip the three rlimit
  computation tests via a `requires_resource` marker when the module is absent.
  The Windows no-op / import-guard tests don't use the real module and still run.
- Fix the `# pragma: no cover` comment on the win32 branch to be accurate.
- Add `enable-cache: true` to the package-smoke setup-uv step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-06-08 15:11:18 +02:00
co-authored by Claude Opus 4.8
parent fc8a4e4dfa
commit 62274069de
5 changed files with 29 additions and 4 deletions
+5 -1
View File
@@ -109,7 +109,6 @@ from nextcloud_mcp_server.config_validators import (
validate_configuration,
)
from nextcloud_mcp_server.context import get_client as get_nextcloud_client
from nextcloud_mcp_server.document_processors import get_registry
from nextcloud_mcp_server.http import nextcloud_httpx_client
from nextcloud_mcp_server.observability import (
ObservabilityMiddleware,
@@ -159,6 +158,11 @@ def initialize_document_processors():
logger.info("Document processing disabled")
return
# Imported lazily so the API startup path never loads the ingest document
# stack (document_processors -> pymupdf -> _isolation) unless document
# processing is actually enabled -- see #877 / the API-vs-ingest split.
from nextcloud_mcp_server.document_processors import get_registry # noqa: PLC0415
registry = get_registry()
registered_count = 0
@@ -25,7 +25,7 @@ from anyio import BrokenWorkerProcess
# importing it unconditionally crashed Windows startup (#877). The RLIMIT_AS cap
# it provides is a Linux-pod safety measure, not a correctness requirement, so on
# platforms without it we fall back to a no-op (``resource is None``).
if sys.platform == "win32": # pragma: no cover - exercised only on Windows
if sys.platform == "win32": # pragma: no cover - win32-only path
resource = None
else:
import resource
+6 -1
View File
@@ -16,7 +16,6 @@ from qdrant_client.models import PointStruct
from nextcloud_mcp_server.acl_hash import compute_acl_hash
from nextcloud_mcp_server.client import NextcloudClient
from nextcloud_mcp_server.config import get_settings
from nextcloud_mcp_server.document_processors import get_registry
from nextcloud_mcp_server.embedding import get_bm25_service, get_embedding_service
from nextcloud_mcp_server.models.deck import DeckCard
from nextcloud_mcp_server.observability.metrics import (
@@ -628,6 +627,12 @@ async def _index_document(
):
# The registry runs the tiered PDF pipeline (tier-0 classify ->
# tier-1 fast -> OCR escalation) and records classification metrics.
# Imported lazily so module import doesn't pull in the document stack
# (document_processors -> _isolation, Unix-only ``resource``; see #877).
from nextcloud_mcp_server.document_processors import ( # noqa: PLC0415
get_registry,
)
registry = get_registry()
try: