Make concurrent database writes wait instead of failing (closes #253) #258

Merged
clawbot merged 1 commits from issue-253-sqlite-busy-timeout into next 2026-10-01 22:16:15 +02:00
Collaborator

SQLite transactions started deferred. When two ran at once and both read before writing, SQLite refused the second write at once with "database is locked" instead of making it wait. TestCreateUserRaceCondition failed this way now and then (#253); any two concurrent writers in upaas could hit it.

internal/database/database.go now opens the database with _txlock=immediate, so each transaction takes the write lock when it begins and a second one waits for it, and with _busy_timeout=5000, so that wait lasts up to 5 seconds.

  • Deviation from the issue: the driver already defaults the busy timeout to 5 seconds. _txlock=immediate is the fix; _busy_timeout=5000 only states the wait in the code.
  • Every transaction now holds the write lock from its start, read-only ones included. All three transactions in upaas write.
  • Judgement call: the migrations tests open their own in-memory database with no concurrent writers, so they are unchanged.

Model: opus-5-5

SQLite transactions started deferred. When two ran at once and both read before writing, SQLite refused the second write at once with "database is locked" instead of making it wait. `TestCreateUserRaceCondition` failed this way now and then (https://git.eeqj.de/sneak/upaas/issues/253); any two concurrent writers in upaas could hit it. `internal/database/database.go` now opens the database with `_txlock=immediate`, so each transaction takes the write lock when it begins and a second one waits for it, and with `_busy_timeout=5000`, so that wait lasts up to 5 seconds. - Deviation from the issue: the driver already defaults the busy timeout to 5 seconds. `_txlock=immediate` is the fix; `_busy_timeout=5000` only states the wait in the code. - Every transaction now holds the write lock from its start, read-only ones included. All three transactions in upaas write. - Judgement call: the migrations tests open their own in-memory database with no concurrent writers, so they are unchanged. Model: opus-5-5
clawbot added the needs-review label 2026-10-01 21:26:52 +02:00
clawbot self-assigned this 2026-10-01 21:26:52 +02:00
Author
Collaborator
  • Conflicts with the current next in TODO.md:23: next now has the #248 entry at the top of Completed Steps, where this PR adds its #253 entry. Acceptable: rebase onto the current next, keep both entries with this one on top, and push the branch again.

Model: opus-5-5

- Conflicts with the current `next` in `TODO.md:23`: `next` now has the https://git.eeqj.de/sneak/upaas/issues/248 entry at the top of Completed Steps, where this PR adds its https://git.eeqj.de/sneak/upaas/issues/253 entry. Acceptable: rebase onto the current `next`, keep both entries with this one on top, and push the branch again. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-01 21:40:15 +02:00
clawbot added needs-rebase and removed needs-rework labels 2026-10-01 21:41:42 +02:00
clawbot added 1 commit 2026-10-01 22:02:16 +02:00
SQLite transactions started deferred, so two that both read and then
wrote could not both proceed, and SQLite refused the second at once with
"database is locked" without waiting. TestCreateUserRaceCondition hit
this now and then.

The database is now opened with _txlock=immediate, so each transaction
takes the write lock when it begins and a second one waits for it, and
with _busy_timeout=5000, so that wait lasts up to 5 seconds. The driver
already defaults to 5000; it is now stated in the code.

Model: opus-5-5
clawbot force-pushed issue-253-sqlite-busy-timeout from e10d4313bc to dd4e9ad4f0 2026-10-01 22:02:16 +02:00 Compare
clawbot added needs-review and removed needs-rebase labels 2026-10-01 22:02:21 +02:00
Author
Collaborator

Review passed.

Model: opus-5-5

Review passed. Model: opus-5-5
clawbot merged commit 047945cabf into next 2026-10-01 22:16:15 +02:00
clawbot deleted branch issue-253-sqlite-busy-timeout 2026-10-01 22:16:15 +02:00
Sign in to join this conversation.