Summary
The *sql.DB is created with no pool or busy-timeout configuration. With WAL and concurrent writers this yields silent SQLITE_BUSY failures surfaced as false/no-op returns.
Root cause
queues.go:18-33:
db, err := sql.Open("sqlite3", dbPath)
db.Exec("PRAGMA journal_mode=WAL;")
SetMaxOpenConns is not set, so database/sql opens multiple connections and lets multiple goroutines attempt concurrent writes.
- No
busy_timeout (DSN _busy_timeout or PRAGMA busy_timeout), so a blocked writer errors immediately instead of waiting.
SQLite allows only one writer at a time; WAL only relaxes reader/writer blocking, not writer/writer.
Impact
Medium. Write operations (Enqueue, dequeue upgrades, Acknowledge) intermittently fail and return false with no error signal, especially under the varmq worker pool this adapter targets.
Possible fix
Cheapest robust option — serialize writers and add a wait:
db, err := sql.Open("sqlite3", dbPath+"?_busy_timeout=5000&_journal_mode=WAL&_txlock=immediate")
if err != nil { ... }
db.SetMaxOpenConns(1) // single writer; SQLite is not a concurrent-write store
SetMaxOpenConns(1) removes writer contention entirely at the cost of write throughput (acceptable for a SQLite-backed queue). If read concurrency matters, keep a higher limit but rely on busy_timeout + BEGIN IMMEDIATE. Setting PRAGMAs via the DSN also guarantees they apply to every pooled connection, not just the first.
Summary
The
*sql.DBis created with no pool or busy-timeout configuration. With WAL and concurrent writers this yields silentSQLITE_BUSYfailures surfaced asfalse/no-op returns.Root cause
queues.go:18-33:SetMaxOpenConnsis not set, sodatabase/sqlopens multiple connections and lets multiple goroutines attempt concurrent writes.busy_timeout(DSN_busy_timeoutorPRAGMA busy_timeout), so a blocked writer errors immediately instead of waiting.SQLite allows only one writer at a time; WAL only relaxes reader/writer blocking, not writer/writer.
Impact
Medium. Write operations (
Enqueue, dequeue upgrades,Acknowledge) intermittently fail and returnfalsewith no error signal, especially under the varmq worker pool this adapter targets.Possible fix
Cheapest robust option — serialize writers and add a wait:
SetMaxOpenConns(1)removes writer contention entirely at the cost of write throughput (acceptable for a SQLite-backed queue). If read concurrency matters, keep a higher limit but rely onbusy_timeout+BEGIN IMMEDIATE. Setting PRAGMAs via the DSN also guarantees they apply to every pooled connection, not just the first.