From 99a200c9d2faf6794d974d7360537c4eeb99f96a Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Mon, 22 Jun 2026 14:05:56 -0400 Subject: [PATCH] Restore None guard, add thread-safety test for _chunk_sync --- .../haiku/rag/chunkers/docling_local.py | 3 ++ tests/test_chunker.py | 28 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/haiku_rag_slim/haiku/rag/chunkers/docling_local.py b/haiku_rag_slim/haiku/rag/chunkers/docling_local.py index 9ab36b88..42bfaffe 100644 --- a/haiku_rag_slim/haiku/rag/chunkers/docling_local.py +++ b/haiku_rag_slim/haiku/rag/chunkers/docling_local.py @@ -177,4 +177,7 @@ class DoclingLocalChunker(DocumentChunker): Returns: List of Chunk containing content and structured metadata. """ + if document is None: + return [] + return await asyncio.to_thread(self._chunk_sync, document) diff --git a/tests/test_chunker.py b/tests/test_chunker.py index e59681a0..3debf339 100644 --- a/tests/test_chunker.py +++ b/tests/test_chunker.py @@ -55,6 +55,34 @@ async def test_local_chunker(qa_corpus: list[dict[str, str]]): assert abs(total_tokens - original_tokens) <= original_tokens * 0.1 +@pytest.mark.asyncio +async def test_local_chunker_runs_off_event_loop_thread(): + """Chunking is CPU-bound; verify it runs in a worker thread.""" + import threading + + chunker = DoclingLocalChunker() + event_loop_thread = threading.current_thread() + called_from: list[threading.Thread] = [] + + original = chunker._chunk_sync + + def recording_chunk_sync(document): + called_from.append(threading.current_thread()) + return original(document) + + chunker._chunk_sync = recording_chunk_sync + + converter = get_converter(Config) + doc = await converter.convert_text("# Hello\n\nWorld", name="test.md") + await chunker.chunk(doc) + + assert called_from, "_chunk_sync was never called" + assert called_from[0] is not event_loop_thread, ( + "_chunk_sync ran on the event-loop thread; " + "it must be dispatched via asyncio.to_thread" + ) + + @pytest.mark.asyncio async def test_local_chunker_custom_config(): """Test DoclingLocalChunker with custom configuration."""