Add timeout config option to set busy timeout on local sqlite3 connections#345
Open
roaminro wants to merge 1 commit into
Open
Add timeout config option to set busy timeout on local sqlite3 connections#345roaminro wants to merge 1 commit into
timeout config option to set busy timeout on local sqlite3 connections#345roaminro wants to merge 1 commit into
Conversation
The native libsql binding already supports a busy timeout via its
Database options ('opts?.timeout ?? 0.0'), but the client never passed
it through, so local connections always opened with no busy handler.
Applying 'PRAGMA busy_timeout' manually doesn't stick either: since
transaction() hands the client's connection to the transaction and
lazily opens a fresh one for the next statement, the pragma is silently
lost after the first interactive transaction. Any later lock contention
(e.g. two processes sharing one database file) then fails instantly
with SQLITE_BUSY instead of waiting.
Passing the timeout through createClient() config applies it natively
to every connection the client opens, including the lazily-created
ones after transaction().
Fixes tursodatabase#288
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a
timeoutoption tocreateClient()config that sets the SQLite busy timeout (in milliseconds) on localfile:databases:Fixes #288.
Problem
There is currently no reliable way to set a busy timeout on a local database:
libsqlbinding already supports a busy timeout (opts?.timeout ?? 0.0→databaseOpen(...)), but the client never passes it through, so every connection opens with no busy handler.PRAGMA busy_timeoutmanually doesn't stick:transaction()hands the client's current connection to the transaction and lazily creates a new connection for the next statement (see Interleaved transactions no longer work #104 / sqlite3: use one connection per transaction #105), silently dropping the pragma. After the first interactive transaction, any lock contention — e.g. two processes sharing one database file — fails instantly withSQLITE_BUSY: database is lockedinstead of waiting.This bites real applications: several downstream projects (we hit this in mastra, Cherry Studio hit it too) ended up patching around it by replaying pragmas after every
transaction()call.Solution
Pass
timeoutthroughexpandConfiginto theDatabaseoptions in the sqlite3 client. Since those options are reused for every lazily-created connection (#getDb()), the busy timeout applies natively to all connections the client opens, including the ones created aftertransaction()— no pragma replay needed.Remote clients ignore the option; it only affects local files (same scope as the native binding's support).
Testing
expandConfigunit test for the new optionPRAGMA busy_timeoutreflects the configured value on a fresh clienttransaction()(regression test for busy_timeout is seemingly ignored (interleaving transactions will always fail) #288)timeoutfails immediately withSQLITE_BUSY, while a client withtimeout: 500waits for the busy handler before giving upnpm run typecheckandnpm run format:checkpass on the changed packages.