Repository navigation
v1.0.0
The general-purpose release: a multi-table Database layer next to the original
single-table MSQLite helper, both on one retry implementation. Existing
MSQLite(path, table, schema) code keeps working unchanged.
Added
Database(path, *, wal=True, timeout_s=30.0, ...)withwrite()(BEGIN IMMEDIATE, or
mode="exclusive") andread()(BEGIN DEFERRED) transactions. Under WAL, the default,
readers never wait for a writer.Transactionwithexecute,executemany,executescript,fetchone,fetchall,
lastrowid,rowcount,row_factoryandconnection.- One connection per thread reused across transactions (
persistent=True);close()and
context-manager support release them. Connections are never carried across a fork. - Lock errors detected by SQLite result code (
SQLITE_BUSY,SQLITE_LOCKED) instead of
message text;SQLITE_BUSY_SNAPSHOTis raised immediately since a retry cannot succeed. - Retry on
BEGIN, on each singleexecuteinside the transaction and onCOMMIT, with
jittered exponential backoff capped atretry_cap_s. Statement retry re-executes only the
failed statement; the transaction stays open. timeout_swall-clock deadline on total lock wait, raisingMSQLiteTimeoutError(elapsed_s, attempts).
MSQLiteMaxRetriesErroris now its subclass, soexcept MSQLiteTimeoutErrorcatches both.- SQLite's own busy timeout (
busy_timeout_s, default 5 s) set on every connection and capped to
the remaining deadline. pragmas=(...)andon_open(connection)for per-connection setup.Database.migrate(steps)keyed onPRAGMA user_version.on_retry(attempt, elapsed_s, error)callback and aStatsdataclass
(executions,retries,max_execution_s,max_wait_s) exposed as.statson both classes.MSQLiteacceptstimeout_s,retry_cap_s,busy_timeout_s,wal,modeandon_retry,
and astrpath as well as aPath.- Logging goes to the
msqlite.msqlitelogger instead of the root logger. - Tests for readers during writes under WAL (threads and processes), the deadline error,
statement-level and commit retry, migrations and the deprecation shims. scripts/benchmark.pyand a benchmark table in the README.- Python 3.15 in the test matrix (the tests run without beartype on a Python it does not support yet); ruff (lint and format) and strict mypy in CI.
Changed
- Connections are opened with
autocommit=Trueand the library issuesBEGIN/COMMIT/ROLLBACK
itself, soexecutescriptno longer risks an implicit commit. MSQLite.__exit__closes every cursor it handed out before closing the connection, so an
unconsumedSELECTcan no longer keep the file lock alive until garbage collection.- Backoff is exponential with jitter (
retry_scaleremains the base unit) rather than a fixed
jittered sleep.
Deprecated
MSQLite.max_execution_time,MSQLite.execution_countandMSQLite.retry_countnow warn
withDeprecationWarning; readMSQLite.stats.max_execution_s,.executionsand.retries.
They will be removed in 1.1.