Add vacuum retention setting
This commit is contained in:
parent
4b4af30e56
commit
c6eaf9d5cd
5 changed files with 87 additions and 4 deletions
BIN
docs/.DS_Store
vendored
BIN
docs/.DS_Store
vendored
Binary file not shown.
BIN
docs/img/.DS_Store
vendored
BIN
docs/img/.DS_Store
vendored
Binary file not shown.
|
|
@ -57,6 +57,11 @@ class AppConfig(BaseModel):
|
||||||
# and error out when the database does not already exist.
|
# and error out when the database does not already exist.
|
||||||
DISABLE_DB_AUTOCREATE: bool = False
|
DISABLE_DB_AUTOCREATE: bool = False
|
||||||
|
|
||||||
|
# Vacuum retention threshold in seconds. Only versions older than this
|
||||||
|
# threshold will be removed during vacuum operations. Default is 60 seconds
|
||||||
|
# to allow concurrent connections to safely use recent versions.
|
||||||
|
VACUUM_RETENTION_SECONDS: int = 60
|
||||||
|
|
||||||
@field_validator("MONITOR_DIRECTORIES", mode="before")
|
@field_validator("MONITOR_DIRECTORIES", mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_monitor_directories(cls, v):
|
def parse_monitor_directories(cls, v):
|
||||||
|
|
|
||||||
|
|
@ -78,14 +78,20 @@ class Store:
|
||||||
if not skip_validation:
|
if not skip_validation:
|
||||||
self._validate_configuration()
|
self._validate_configuration()
|
||||||
|
|
||||||
def vacuum(self) -> None:
|
def vacuum(self, retention_seconds: int = Config.VACUUM_RETENTION_SECONDS) -> None:
|
||||||
"""Optimize and clean up old versions across all tables to reduce disk usage."""
|
"""Optimize and clean up old versions across all tables to reduce disk usage.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
retention_seconds: Retention threshold in seconds. Only versions older
|
||||||
|
than this will be removed. Defaults to Config.VACUUM_RETENTION_SECONDS.
|
||||||
|
"""
|
||||||
if self._has_cloud_config() and str(Config.LANCEDB_URI).startswith("db://"):
|
if self._has_cloud_config() and str(Config.LANCEDB_URI).startswith("db://"):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Perform maintenance per table using optimize() with cleanup_older_than 0
|
# Perform maintenance per table using optimize() with configurable retention
|
||||||
|
retention = timedelta(seconds=retention_seconds)
|
||||||
for table in [self.documents_table, self.chunks_table, self.settings_table]:
|
for table in [self.documents_table, self.chunks_table, self.settings_table]:
|
||||||
table.optimize(cleanup_older_than=timedelta(0))
|
table.optimize(cleanup_older_than=retention)
|
||||||
|
|
||||||
def _connect_to_lancedb(self, db_path: Path):
|
def _connect_to_lancedb(self, db_path: Path):
|
||||||
"""Establish connection to LanceDB (local, cloud, or object storage)."""
|
"""Establish connection to LanceDB (local, cloud, or object storage)."""
|
||||||
|
|
|
||||||
|
|
@ -122,3 +122,75 @@ def test_existing_database_runs_upgrades(monkeypatch, temp_db_path):
|
||||||
Store(temp_db_path)
|
Store(temp_db_path)
|
||||||
|
|
||||||
assert called["value"]
|
assert called["value"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_vacuum_with_retention_threshold(temp_db_path):
|
||||||
|
store = Store(temp_db_path)
|
||||||
|
repo = DocumentRepository(store)
|
||||||
|
|
||||||
|
# Stub embeddings to avoid network
|
||||||
|
dim = repo.chunk_repository.embedder._vector_dim
|
||||||
|
|
||||||
|
async def fake_embed(x): # type: ignore[no-redef]
|
||||||
|
if isinstance(x, list):
|
||||||
|
return [[0.0] * dim for _ in x]
|
||||||
|
return [0.0] * dim
|
||||||
|
|
||||||
|
repo.chunk_repository.embedder.embed = fake_embed # type: ignore[assignment]
|
||||||
|
|
||||||
|
# Create first document
|
||||||
|
doc1 = Document(content="First document")
|
||||||
|
dl_doc1 = text_to_docling_document("First document", name="doc1.md")
|
||||||
|
await repo._create_with_docling(doc1, dl_doc1)
|
||||||
|
|
||||||
|
# Create second document
|
||||||
|
doc2 = Document(content="Second document")
|
||||||
|
dl_doc2 = text_to_docling_document("Second document", name="doc2.md")
|
||||||
|
await repo._create_with_docling(doc2, dl_doc2)
|
||||||
|
|
||||||
|
# Get initial version counts (should have multiple versions from creates)
|
||||||
|
initial_doc_versions = len(list(store.documents_table.list_versions()))
|
||||||
|
initial_chunk_versions = len(list(store.chunks_table.list_versions()))
|
||||||
|
|
||||||
|
assert initial_doc_versions > 1, "Should have multiple document table versions"
|
||||||
|
assert initial_chunk_versions > 1, "Should have multiple chunk table versions"
|
||||||
|
|
||||||
|
# Vacuum with default threshold (60 seconds) - should keep recent versions
|
||||||
|
# Note: vacuum may create new versions even when not cleaning up old ones
|
||||||
|
store.vacuum()
|
||||||
|
|
||||||
|
after_default_doc_versions = len(list(store.documents_table.list_versions()))
|
||||||
|
after_default_chunk_versions = len(list(store.chunks_table.list_versions()))
|
||||||
|
|
||||||
|
# After vacuum with retention, version count should stay the same or increase
|
||||||
|
# (optimize may create new versions) but not decrease
|
||||||
|
assert after_default_doc_versions >= initial_doc_versions, (
|
||||||
|
"Default vacuum should not remove recent versions"
|
||||||
|
)
|
||||||
|
assert after_default_chunk_versions >= initial_chunk_versions, (
|
||||||
|
"Default vacuum should not remove recent versions"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Vacuum with 0 threshold - should significantly reduce versions
|
||||||
|
store.vacuum(retention_seconds=0)
|
||||||
|
|
||||||
|
after_zero_doc_versions = len(list(store.documents_table.list_versions()))
|
||||||
|
after_zero_chunk_versions = len(list(store.chunks_table.list_versions()))
|
||||||
|
|
||||||
|
# After aggressive vacuum, should have minimal versions (1-2)
|
||||||
|
# Note: optimize operation may create a version after cleanup
|
||||||
|
assert after_zero_doc_versions <= 2, (
|
||||||
|
f"Should have minimal document versions after vacuum(0), got {after_zero_doc_versions}"
|
||||||
|
)
|
||||||
|
assert after_zero_chunk_versions <= 2, (
|
||||||
|
f"Should have minimal chunk versions after vacuum(0), got {after_zero_chunk_versions}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# And it should be significantly fewer than before
|
||||||
|
assert after_zero_doc_versions < initial_doc_versions, (
|
||||||
|
"Should have fewer versions after vacuum(0)"
|
||||||
|
)
|
||||||
|
assert after_zero_chunk_versions < initial_chunk_versions, (
|
||||||
|
"Should have fewer versions after vacuum(0)"
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue