mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-09-21 17:08:33 +00:00
Fix: rebuild the search index automatically when it is corrupted, instead of hard-failing (#14180)
This commit is contained in:
@@ -337,4 +337,13 @@ def open_or_rebuild_index(index_dir: Path | None = None) -> tantivy.Index:
|
|||||||
idx = tantivy.Index(build_schema(), path=str(index_dir))
|
idx = tantivy.Index(build_schema(), path=str(index_dir))
|
||||||
_write_sentinels(index_dir)
|
_write_sentinels(index_dir)
|
||||||
return idx
|
return idx
|
||||||
return tantivy.Index.open(str(index_dir))
|
try:
|
||||||
|
return tantivy.Index.open(str(index_dir))
|
||||||
|
except ValueError:
|
||||||
|
logger.exception(
|
||||||
|
"Search index is corrupted or incomplete - rebuilding from scratch.",
|
||||||
|
)
|
||||||
|
wipe_index(index_dir)
|
||||||
|
idx = tantivy.Index(build_schema(), path=str(index_dir))
|
||||||
|
_write_sentinels(index_dir)
|
||||||
|
return idx
|
||||||
|
|||||||
@@ -21,9 +21,11 @@ import pytest
|
|||||||
import tantivy
|
import tantivy
|
||||||
from django.conf import settings as django_settings
|
from django.conf import settings as django_settings
|
||||||
|
|
||||||
|
from documents.search._schema import SCHEMA_VERSION
|
||||||
from documents.search._schema import build_schema
|
from documents.search._schema import build_schema
|
||||||
from documents.search._schema import needs_rebuild
|
from documents.search._schema import needs_rebuild
|
||||||
from documents.search._schema import open_or_rebuild_index
|
from documents.search._schema import open_or_rebuild_index
|
||||||
|
from documents.search._schema import schema_fingerprint
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -176,3 +178,50 @@ class TestUpgradeFromReleasedV1Index:
|
|||||||
open_or_rebuild_index(released_v1_index)
|
open_or_rebuild_index(released_v1_index)
|
||||||
|
|
||||||
assert needs_rebuild(released_v1_index) is False
|
assert needs_rebuild(released_v1_index) is False
|
||||||
|
|
||||||
|
|
||||||
|
class TestCorruptedIndex:
|
||||||
|
@pytest.fixture
|
||||||
|
def current_index_missing_meta_json(self, tmp_path: Path) -> Path:
|
||||||
|
"""A current-schema index directory whose meta.json has gone missing.
|
||||||
|
|
||||||
|
The sentinel matches the current schema, so needs_rebuild() reports
|
||||||
|
False and open_or_rebuild_index() takes the plain Index.open() path.
|
||||||
|
"""
|
||||||
|
index_dir = tmp_path / "index"
|
||||||
|
index_dir.mkdir()
|
||||||
|
tantivy.Index(build_schema(), path=str(index_dir))
|
||||||
|
(index_dir / ".index_settings.json").write_text(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"schema_version": SCHEMA_VERSION,
|
||||||
|
"language": django_settings.SEARCH_LANGUAGE,
|
||||||
|
"schema_fingerprint": schema_fingerprint(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
(index_dir / "meta.json").unlink()
|
||||||
|
return index_dir
|
||||||
|
|
||||||
|
def test_missing_meta_json_is_rebuilt_instead_of_raising(
|
||||||
|
self,
|
||||||
|
current_index_missing_meta_json: Path,
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
GIVEN:
|
||||||
|
- An index directory with a sentinel matching the current
|
||||||
|
schema, but a missing/corrupted meta.json (e.g. an
|
||||||
|
interrupted write left the directory in a torn state)
|
||||||
|
WHEN:
|
||||||
|
- open_or_rebuild_index() is called against it
|
||||||
|
THEN:
|
||||||
|
- It rebuilds the index instead of letting tantivy's
|
||||||
|
ValueError propagate; before this, a corrupted index left
|
||||||
|
every read, write, and `document_index reindex --if-needed`
|
||||||
|
hard-failing indefinitely, since the sentinel already
|
||||||
|
matched and reported the index as up to date
|
||||||
|
"""
|
||||||
|
open_or_rebuild_index(current_index_missing_meta_json)
|
||||||
|
|
||||||
|
assert (current_index_missing_meta_json / "meta.json").exists()
|
||||||
|
tantivy.Index.open(str(current_index_missing_meta_json))
|
||||||
|
|||||||
Reference in New Issue
Block a user