Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e64435e66 |
@@ -530,12 +530,10 @@ Key settings in more detail:
|
|||||||
- `db_url` — the SQLite database to open; omitted, it is
|
- `db_url` — the SQLite database to open; omitted, it is
|
||||||
`file:<state_dir>/state.sqlite3?_pragma=journal_mode(WAL)`, which keeps the
|
`file:<state_dir>/state.sqlite3?_pragma=journal_mode(WAL)`, which keeps the
|
||||||
database in WAL mode. pixa opens one connection to it, so its own reads and
|
database in WAL mode. pixa opens one connection to it, so its own reads and
|
||||||
writes run one at a time. Requests wait while eviction runs one of its
|
writes run one at a time. It adds `_pragma=busy_timeout(5000)` to any
|
||||||
queries, some of which read a whole table. pixa adds
|
`db_url`, so a write that finds another program writing to the file waits up
|
||||||
`_pragma=busy_timeout(5000)` to any `db_url`, so a write that finds another
|
to five seconds for it instead of failing. WAL mode comes only from the URL:
|
||||||
program writing to the file waits up to five seconds for it instead of
|
keep `_pragma=journal_mode(WAL)` in one you set
|
||||||
failing. WAL mode comes only from the URL: keep `_pragma=journal_mode(WAL)` in
|
|
||||||
one you set
|
|
||||||
- `cache_max_bytes` — disk cache size limit in bytes; `0` disables the disk
|
- `cache_max_bytes` — disk cache size limit in bytes; `0` disables the disk
|
||||||
cache entirely; omitted defaults to 75% of the sum of the free space on the
|
cache entirely; omitted defaults to 75% of the sum of the free space on the
|
||||||
filesystem containing `<state_dir>/cache/` and the bytes of source and
|
filesystem containing `<state_dir>/cache/` and the bytes of source and
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ P2: security: per-IP rate limiting on the image routes
|
|||||||
|
|
||||||
- 2026-10-08 SQLite writes no longer fail with "database is locked" under load
|
- 2026-10-08 SQLite writes no longer fail with "database is locked" under load
|
||||||
(closes #223): `internal/database` opens the database with one connection, so
|
(closes #223): `internal/database` opens the database with one connection, so
|
||||||
pixa's own reads and writes run on it one at a time instead of competing for
|
pixa's own reads and writes wait for it in turn instead of competing for
|
||||||
SQLite's lock, where a write that kept losing could wait past the five-second
|
SQLite's lock, where a write that kept losing could wait past the five-second
|
||||||
busy timeout and be lost. The busy timeout stays, for another program writing
|
busy timeout and be lost. The busy timeout stays, for another program writing
|
||||||
to the same file. No code in pixa keeps rows or a transaction open while it
|
to the same file. No code in pixa keeps rows or a transaction open while it
|
||||||
|
|||||||
@@ -13,10 +13,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// TestConcurrentWritesAllSucceed opens a database the way pixad does and
|
// TestConcurrentWritesAllSucceed opens a database the way pixad does and
|
||||||
// writes to it from several goroutines at once, as one request's writes and
|
// writes to it from several goroutines at once, so the writes run on
|
||||||
// the background eviction pass do. Every write must succeed, none failing
|
// separate connections, as one request's writes and the background eviction
|
||||||
// with "database is locked", whether or not db_url already has parameters,
|
// pass do. Every write must succeed, none failing with "database is locked",
|
||||||
// and the parameters it has must still apply.
|
// whether or not db_url already has parameters, and the parameters it has
|
||||||
|
// must still apply.
|
||||||
func TestConcurrentWritesAllSucceed(t *testing.T) {
|
func TestConcurrentWritesAllSucceed(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
@@ -265,9 +265,9 @@ func (s *Database) connect(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// One connection: pixa's own reads and writes run on it one at a
|
// One connection: pixa's own reads and writes wait for it in turn
|
||||||
// time instead of competing for SQLite's lock, where a write that
|
// instead of competing for SQLite's lock, where a write that keeps
|
||||||
// keeps losing can wait past the busy timeout and be lost.
|
// losing can wait past the busy timeout and be lost.
|
||||||
db.SetMaxOpenConns(1)
|
db.SetMaxOpenConns(1)
|
||||||
|
|
||||||
err = db.PingContext(ctx)
|
err = db.PingContext(ctx)
|
||||||
|
|||||||
Reference in New Issue
Block a user