fix(db): prevent SQLite "database is locked" errors under concurrent writes

Configure SQLite connections with WAL journal mode, a 5-second busy
timeout, shared cache, and a max of 1 open connection. SQLite only
supports a single writer at a time, so without these settings concurrent
API requests (e.g. bulk task creation) would immediately fail with
"database is locked" instead of waiting and retrying.
This commit is contained in:
kolaente
2026-03-02 12:37:17 +01:00
parent 1ba6a74383
commit 79dbb40985
2 changed files with 16 additions and 2 deletions

2
.gitignore vendored
View File

@@ -9,6 +9,8 @@ config.yml.sample
!.gitea/ISSUE_TEMPLATE/config.yml !.gitea/ISSUE_TEMPLATE/config.yml
docs/themes/ docs/themes/
*.db *.db
*.db-shm
*.db-wal
Run Run
dist/ dist/
cover.* cover.*

View File

@@ -250,7 +250,13 @@ func initSqliteEngine() (engine *xorm.Engine, err error) {
} }
if path == "memory" { if path == "memory" {
return xorm.NewEngine("sqlite3", "file::memory:?cache=shared") engine, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared&_busy_timeout=5000")
if err != nil {
return
}
engine.SetMaxOpenConns(1)
engine.SetMaxIdleConns(1)
return
} }
// Log the resolved database path // Log the resolved database path
@@ -276,7 +282,13 @@ func initSqliteEngine() (engine *xorm.Engine, err error) {
_ = os.Remove(path) // Remove the file to not prevent the db from creating another one _ = os.Remove(path) // Remove the file to not prevent the db from creating another one
} }
return xorm.NewEngine("sqlite3", path) engine, err = xorm.NewEngine("sqlite3", path+"?cache=shared&_busy_timeout=5000&_journal_mode=WAL")
if err != nil {
return
}
engine.SetMaxOpenConns(1)
engine.SetMaxIdleConns(1)
return
} }
// getUserDataDir returns the platform-appropriate directory for application data // getUserDataDir returns the platform-appropriate directory for application data