mirror of
https://github.com/xpltdco/media-rip.git
synced 2026-04-03 02:53:58 -06:00
fix: probe WAL with test write + close/reopen fallback for CIFS
The PRAGMA journal_mode=WAL returns 'wal' even on CIFS mounts where WAL shared-memory actually fails. Now we do a concrete test write after setting WAL mode; if it fails, we close the connection, remove stale WAL/SHM files, reopen in DELETE mode.
This commit is contained in:
parent
3205c101c3
commit
6682438163
1 changed files with 49 additions and 21 deletions
|
|
@ -103,30 +103,36 @@ async def init_db(db_path: str) -> aiosqlite.Connection:
|
||||||
# --- PRAGMAs (before any DDL) ---
|
# --- PRAGMAs (before any DDL) ---
|
||||||
await db.execute("PRAGMA busy_timeout = 5000")
|
await db.execute("PRAGMA busy_timeout = 5000")
|
||||||
|
|
||||||
# Attempt WAL mode; if the underlying filesystem doesn't support the
|
# Attempt WAL mode, then verify it actually works by doing a test write.
|
||||||
# shared-memory primitives WAL requires (CIFS, NFS, some FUSE mounts),
|
# On CIFS/NFS/FUSE mounts WAL's shared-memory primitives silently fail
|
||||||
# the PRAGMA silently stays on the previous mode or returns an error.
|
# even though the PRAGMA returns "wal". A concrete write attempt is the
|
||||||
# In that case, fall back to DELETE mode which works everywhere.
|
# only reliable way to detect this.
|
||||||
try:
|
journal_mode = await _try_journal_mode(db, "wal")
|
||||||
result = await db.execute("PRAGMA journal_mode = WAL")
|
|
||||||
row = await result.fetchone()
|
|
||||||
journal_mode = row[0] if row else "unknown"
|
|
||||||
except Exception:
|
|
||||||
journal_mode = "error"
|
|
||||||
|
|
||||||
if journal_mode != "wal":
|
if journal_mode == "wal":
|
||||||
logger.warning(
|
|
||||||
"WAL mode unavailable (got %s) — falling back to DELETE mode "
|
|
||||||
"(network/CIFS filesystem?)",
|
|
||||||
journal_mode,
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
result = await db.execute("PRAGMA journal_mode = DELETE")
|
# Probe with an actual write — WAL on CIFS explodes here
|
||||||
row = await result.fetchone()
|
await db.execute(
|
||||||
journal_mode = row[0] if row else "unknown"
|
"CREATE TABLE IF NOT EXISTS _wal_probe (_x INTEGER)"
|
||||||
|
)
|
||||||
|
await db.execute("DROP TABLE IF EXISTS _wal_probe")
|
||||||
|
await db.commit()
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.warning("Failed to set DELETE journal mode, continuing with default")
|
logger.warning(
|
||||||
journal_mode = "default"
|
"WAL mode set but write failed — filesystem likely lacks "
|
||||||
|
"shared-memory support (CIFS/NFS?). Switching to DELETE mode."
|
||||||
|
)
|
||||||
|
# Close and reopen so SQLite drops the broken WAL state
|
||||||
|
await db.close()
|
||||||
|
# Remove stale WAL/SHM files that the broken open left behind
|
||||||
|
import pathlib
|
||||||
|
for suffix in ("-wal", "-shm"):
|
||||||
|
p = pathlib.Path(db_path + suffix)
|
||||||
|
p.unlink(missing_ok=True)
|
||||||
|
db = await aiosqlite.connect(db_path)
|
||||||
|
db.row_factory = aiosqlite.Row
|
||||||
|
await db.execute("PRAGMA busy_timeout = 5000")
|
||||||
|
journal_mode = await _try_journal_mode(db, "delete")
|
||||||
|
|
||||||
logger.info("journal_mode set to %s", journal_mode)
|
logger.info("journal_mode set to %s", journal_mode)
|
||||||
|
|
||||||
|
|
@ -140,6 +146,28 @@ async def init_db(db_path: str) -> aiosqlite.Connection:
|
||||||
return db
|
return db
|
||||||
|
|
||||||
|
|
||||||
|
async def _try_journal_mode(
|
||||||
|
db: aiosqlite.Connection, mode: str,
|
||||||
|
) -> str:
|
||||||
|
"""Try setting *mode* and return the actual journal mode string."""
|
||||||
|
try:
|
||||||
|
result = await db.execute(f"PRAGMA journal_mode = {mode}")
|
||||||
|
row = await result.fetchone()
|
||||||
|
return (row[0] if row else "unknown").lower()
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning("PRAGMA journal_mode=%s failed: %s", mode, exc)
|
||||||
|
return "error"
|
||||||
|
|
||||||
|
await db.execute("PRAGMA synchronous = NORMAL")
|
||||||
|
|
||||||
|
# --- Schema ---
|
||||||
|
await db.executescript(_TABLES)
|
||||||
|
await db.executescript(_INDEXES)
|
||||||
|
logger.info("Database tables and indexes created at %s", db_path)
|
||||||
|
|
||||||
|
return db
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# CRUD helpers
|
# CRUD helpers
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue