on main help sign in
fix(sqlite): increase busy timeout (#2181)

Also refactor so we have the same pragmas on both drivers. I couldn't reproduce OP's issue, but they're likely trying to use many Crush instances at the same time, which may cause this. The timeout was 5s only, so it was kind of easy to hit under load, I presume. Upping it to 30s should improve that. AFAIK there's no much else we can do. See https://www.sqlite.org/rescode.html#busy Closes #2129 Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>

commit48157c6c4eac6af31bda49697f0ef26b90d88df6 authorCarlos Alexandro Becker <caarlos0@users.noreply.github.com> dateTue 10 Feb 2026, 15:31 (8 months ago) parent09cea77
3 files changed+20−21
internal/db/connect.go+10 internal/db/connect_modernc.go+4−7 internal/db/connect_ncruces.go+6−14
internal/db/connect.go+10
@@ -10,6 +10,16 @@ import (
1010 "github.com/pressly/goose/v3"
1111)
1212
13+var pragmas = map[string]string{
14+ "foreign_keys": "ON",
15+ "journal_mode": "WAL",
16+ "page_size": "4096",
17+ "cache_size": "-8000",
18+ "synchronous": "NORMAL",
19+ "secure_delete": "ON",
20+ "busy_timeout": "30000",
21+}
22+
1323// Connect opens a SQLite database connection and runs migrations.
1424func Connect(ctx context.Context, dataDir string) (*sql.DB, error) {
1525 if dataDir == "" {
internal/db/connect_modernc.go+4−7
@@ -14,18 +14,15 @@ func openDB(dbPath string) (*sql.DB, error) {
1414 // Set pragmas for better performance via _pragma query params.
1515 // Format: _pragma=name(value)
1616 params := url.Values{}
17− params.Add("_pragma", "foreign_keys(on)")
18− params.Add("_pragma", "journal_mode(WAL)")
19− params.Add("_pragma", "page_size(4096)")
20− params.Add("_pragma", "cache_size(-8000)")
21− params.Add("_pragma", "synchronous(NORMAL)")
22− params.Add("_pragma", "secure_delete(on)")
23− params.Add("_pragma", "busy_timeout(5000)")
17+ for name, value := range pragmas {
18+ params.Add("_pragma", fmt.Sprintf("%s(%s)", name, value))
19+ }
2420
2521 dsn := fmt.Sprintf("file:%s?%s", dbPath, params.Encode())
2622 db, err := sql.Open("sqlite", dsn)
2723 if err != nil {
2824 return nil, fmt.Errorf("failed to open database: %w", err)
2925 }
26+
3027 return db, nil
3128}
internal/db/connect_ncruces.go+6−14
@@ -12,21 +12,12 @@ import (
1212)
1313
1414func openDB(dbPath string) (*sql.DB, error) {
15− // Set pragmas for better performance.
16− pragmas := []string{
17− "PRAGMA foreign_keys = ON;",
18− "PRAGMA journal_mode = WAL;",
19− "PRAGMA page_size = 4096;",
20− "PRAGMA cache_size = -8000;",
21− "PRAGMA synchronous = NORMAL;",
22− "PRAGMA secure_delete = ON;",
23− "PRAGMA busy_timeout = 5000;",
24− }
25−
2615 db, err := driver.Open(dbPath, func(c *sqlite3.Conn) error {
27− for _, pragma := range pragmas {
28− if err := c.Exec(pragma); err != nil {
29− return fmt.Errorf("failed to set pragma %q: %w", pragma, err)
16+ // Set pragmas for better performance via _pragma query params.
17+ // Format: PRAGMA name = value;
18+ for name, value := range pragmas {
19+ if err := c.Exec(fmt.Sprintf("PRAGMA %s = %s;", name, value)); err != nil {
20+ return fmt.Errorf("failed to set pragma %q: %w", name, err)
3021 }
3122 }
3223 return nil
@@ -34,5 +25,6 @@ func openDB(dbPath string) (*sql.DB, error) {
3425 if err != nil {
3526 return nil, fmt.Errorf("failed to open database: %w", err)
3627 }
28+
3729 return db, nil
3830}