fix: Create fresh DB template and atomically swap it
- Unit tests tend to fail due inconsitent DB file. - Create a fresh copy on a temporary location and the atomically swap it. - To always provide a completely initialized and migrated DB.
This commit is contained in:
@@ -36,11 +36,26 @@ def create_template(output_path: str = "build/.template-migrated.db") -> None:
|
||||
out = Path(output_path)
|
||||
out.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Remove existing template so we always create fresh
|
||||
if out.exists():
|
||||
out.unlink()
|
||||
# Remove existing template and any SQLite journal/WAL files so we always
|
||||
# create fresh. SQLite may leave behind -wal/-shm files that prevent
|
||||
# clean recreation.
|
||||
for suffix in ("", "-wal", "-shm", "-journal"):
|
||||
candidate = out.with_name(out.name + suffix)
|
||||
if candidate.exists():
|
||||
candidate.unlink(missing_ok=True)
|
||||
|
||||
db_url = f"sqlite:///{out.resolve()}"
|
||||
# Use a temporary file path to avoid race conditions with parallel
|
||||
# workers that may still be reading the old template. We create the
|
||||
# database at a unique temp path, then atomically rename it into place.
|
||||
import tempfile
|
||||
|
||||
fd, tmp_path = tempfile.mkstemp(
|
||||
dir=out.parent, prefix=f".{out.name}.tmp.", suffix=".db"
|
||||
)
|
||||
os.close(fd)
|
||||
tmp = Path(tmp_path)
|
||||
|
||||
db_url = f"sqlite:///{tmp.resolve()}"
|
||||
engine = create_engine(db_url, connect_args={"check_same_thread": False})
|
||||
|
||||
# Create all 33 tables in one fast DDL batch
|
||||
@@ -71,6 +86,10 @@ def create_template(output_path: str = "build/.template-migrated.db") -> None:
|
||||
|
||||
engine.dispose()
|
||||
|
||||
# Atomically move the temp database into place. This ensures parallel
|
||||
# workers never see a partially-written template.
|
||||
tmp.replace(out)
|
||||
|
||||
# Ensure the template database is writable (0o664 = rw-rw-r--)
|
||||
# This prevents sqlite3.OperationalError: attempt to write a readonly database
|
||||
# when tests copy and modify the template during test setup.
|
||||
|
||||
Reference in New Issue
Block a user