Stop writing the schema version on database open
This commit is contained in:
parent
e70f271ac7
commit
b6bbea3d64
3 changed files with 33 additions and 18 deletions
|
|
@ -1,6 +1,10 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Opening a database no longer writes to it: reads no longer rewrite the stored embedding settings or change the stored version, and the version is never downgraded.
|
||||||
|
|
||||||
## [0.54.0] - 2026-06-04
|
## [0.54.0] - 2026-06-04
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import lancedb
|
||||||
import pyarrow as pa
|
import pyarrow as pa
|
||||||
from lancedb.index import FTS, BTree, IvfPq
|
from lancedb.index import FTS, BTree, IvfPq
|
||||||
from lancedb.pydantic import LanceModel, Vector
|
from lancedb.pydantic import LanceModel, Vector
|
||||||
|
from packaging.version import parse
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
|
|
||||||
from haiku.rag.config import AppConfig, Config
|
from haiku.rag.config import AppConfig, Config
|
||||||
|
|
@ -509,7 +510,7 @@ class Store:
|
||||||
await self.set_haiku_version(metadata.version("haiku.rag-slim"))
|
await self.set_haiku_version(metadata.version("haiku.rag-slim"))
|
||||||
|
|
||||||
async def _check_migrations(self) -> None:
|
async def _check_migrations(self) -> None:
|
||||||
"""Check if migrations are pending and error or update version accordingly.
|
"""Raise if migrations are pending. Opening never writes the version.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
MigrationRequiredError: If migrations are pending.
|
MigrationRequiredError: If migrations are pending.
|
||||||
|
|
@ -529,10 +530,6 @@ class Store:
|
||||||
"Run 'haiku-rag migrate' to upgrade."
|
"Run 'haiku-rag migrate' to upgrade."
|
||||||
)
|
)
|
||||||
|
|
||||||
# No pending migrations - update version silently if needed (writable only)
|
|
||||||
if not self._read_only and db_version != current_version:
|
|
||||||
await self.set_haiku_version(current_version)
|
|
||||||
|
|
||||||
async def migrate(self) -> list[str]:
|
async def migrate(self) -> list[str]:
|
||||||
"""Run pending database migrations.
|
"""Run pending database migrations.
|
||||||
|
|
||||||
|
|
@ -551,8 +548,9 @@ class Store:
|
||||||
|
|
||||||
applied = await run_pending_upgrades(self, db_version)
|
applied = await run_pending_upgrades(self, db_version)
|
||||||
|
|
||||||
# Update version after successful migration
|
# Advance the schema marker only forward — never downgrade a database
|
||||||
if applied or db_version != current_version:
|
# opened with an older build than last stamped it.
|
||||||
|
if parse(current_version) > parse(db_version):
|
||||||
await self.set_haiku_version(current_version)
|
await self.set_haiku_version(current_version)
|
||||||
|
|
||||||
return applied
|
return applied
|
||||||
|
|
|
||||||
|
|
@ -38,21 +38,19 @@ class TestMigrationCheck:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_version_bump_without_pending_migrations_updates_silently(
|
async def test_open_does_not_change_version(self, temp_db_path):
|
||||||
self, temp_db_path
|
"""Opening a database never writes the version, even when it differs.
|
||||||
):
|
|
||||||
"""When version is outdated but no migrations pending, update version silently."""
|
A version newer than all upgrade steps has no pending migrations, so the
|
||||||
|
open succeeds; the stored version must be left untouched (no downgrade,
|
||||||
|
no bump) because opening is a pure read.
|
||||||
|
"""
|
||||||
async with Store(temp_db_path, create=True) as store:
|
async with Store(temp_db_path, create=True) as store:
|
||||||
# Set an older version that has no pending migrations
|
|
||||||
# (newer than all current upgrade steps)
|
|
||||||
await store.set_haiku_version("100.0.0")
|
await store.set_haiku_version("100.0.0")
|
||||||
|
|
||||||
# Re-open - should update version silently, no error
|
# Re-open writable - no error, version unchanged
|
||||||
async with Store(temp_db_path) as store:
|
async with Store(temp_db_path) as store:
|
||||||
# Version should now be current
|
assert await store.get_haiku_version() == "100.0.0"
|
||||||
version = await store.get_haiku_version()
|
|
||||||
expected = metadata.version("haiku.rag-slim")
|
|
||||||
assert version == expected
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_pending_migrations_raises_error(self, temp_db_path):
|
async def test_pending_migrations_raises_error(self, temp_db_path):
|
||||||
|
|
@ -160,6 +158,21 @@ class TestMigrateMethod:
|
||||||
applied = await store.migrate()
|
applied = await store.migrate()
|
||||||
assert applied == []
|
assert applied == []
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_migrate_does_not_downgrade_future_version(self, temp_db_path):
|
||||||
|
"""migrate() must not move the version backwards.
|
||||||
|
|
||||||
|
Running an older build's migrate against a DB stamped with a newer
|
||||||
|
version (no pending upgrades) leaves the stored version untouched.
|
||||||
|
"""
|
||||||
|
async with Store(temp_db_path, create=True) as store:
|
||||||
|
await store.set_haiku_version("100.0.0")
|
||||||
|
|
||||||
|
async with Store(temp_db_path, skip_migration_check=True) as store:
|
||||||
|
applied = await store.migrate()
|
||||||
|
assert applied == []
|
||||||
|
assert await store.get_haiku_version() == "100.0.0"
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_migrate_raises_read_only_error(self, temp_db_path):
|
async def test_migrate_raises_read_only_error(self, temp_db_path):
|
||||||
"""Store.migrate() should raise ReadOnlyError in read-only mode."""
|
"""Store.migrate() should raise ReadOnlyError in read-only mode."""
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue