Spaces:
Running
Running
| """Regression tests for re-chunking a document while it is | |
| still processing must not queue a second concurrent ingestion run. | |
| update_chunk_settings previously reset doc.status to "pending" and | |
| re-queued process_document.delay(...) unconditionally, with no check on | |
| the document's current status. If a prior ingestion run for the same | |
| document_id was still "processing", this let two ingestion runs execute | |
| concurrently against the same document - and since store_chunks() in | |
| vectorstore.py performs a non-atomic delete-then-batch-insert sequence, | |
| the two runs could interleave and corrupt the vector store relative to | |
| whatever chunk_count ends up persisted in Postgres. | |
| """ | |
| from app.models import Document | |
| def test_update_chunk_settings_rejects_while_document_processing( | |
| client, auth_headers, db_session, user, monkeypatch | |
| ): | |
| """A document mid-ingestion must reject a re-chunk request with 409, | |
| not silently reset its status and re-queue a second concurrent run. | |
| """ | |
| document = Document( | |
| user_id=user.id, | |
| filename="processing.pdf", | |
| original_name="processing.pdf", | |
| file_size=256, | |
| status="processing", | |
| chunk_count=0, | |
| page_count=0, | |
| ) | |
| db_session.add(document) | |
| db_session.commit() | |
| db_session.refresh(document) | |
| def _delay_should_not_be_called(*args, **kwargs): | |
| raise AssertionError( | |
| "process_document.delay was called for a document still " | |
| "processing - the concurrency guard did not reject the request" | |
| ) | |
| monkeypatch.setattr( | |
| "app.routes.documents.process_document.delay", | |
| _delay_should_not_be_called, | |
| ) | |
| response = client.post( | |
| f"/api/v1/documents/{document.id}/chunk_settings", | |
| json={"chunk_size": 500, "chunk_overlap": 50}, | |
| headers=auth_headers, | |
| ) | |
| assert response.status_code == 409 | |
| refreshed = db_session.get(Document, document.id) | |
| assert refreshed.status == "processing" | |
| assert refreshed.chunk_count == 0 | |
| assert refreshed.page_count == 0 | |
| def test_update_chunk_settings_allows_when_not_processing( | |
| client, auth_headers, ready_document, db_session, monkeypatch | |
| ): | |
| """A document that is "ready" (i.e. not mid-ingestion) must still be | |
| allowed to re-chunk - the guard should only block "processing". | |
| """ | |
| queued = {} | |
| class _FakeTask: | |
| id = "fake-task-id" | |
| def _fake_delay(**kwargs): | |
| queued.update(kwargs) | |
| return _FakeTask() | |
| monkeypatch.setattr("app.routes.documents.process_document.delay", _fake_delay) | |
| response = client.post( | |
| f"/api/v1/documents/{ready_document.id}/chunk_settings", | |
| json={"chunk_size": 500, "chunk_overlap": 50}, | |
| headers=auth_headers, | |
| ) | |
| assert response.status_code == 200 | |
| assert queued["document_id"] == ready_document.id | |
| refreshed = db_session.get(Document, ready_document.id) | |
| assert refreshed.status == "pending" | |
| assert refreshed.chunk_size == 500 | |
| assert refreshed.chunk_overlap == 50 |