From ab5be2f50e28b254c9807bc43d7d14093c7d5064 Mon Sep 17 00:00:00 2001 From: KaNaDaAT Date: Thu, 15 May 2025 20:53:16 +0200 Subject: [PATCH] fix(db): prevent "database is locked" errors by improving SQLite usage - Add explicit rows.Close() calls inside loops to avoid holding locks too long - Add SQLite busy timeout (5s) to connection string to wait for locks instead of failing immediately --- server/db/sqlite.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/server/db/sqlite.go b/server/db/sqlite.go index 03691a6..6cffcf7 100644 --- a/server/db/sqlite.go +++ b/server/db/sqlite.go @@ -15,6 +15,15 @@ type SQLiteClient struct { } func NewSQLiteClient(dataSourceName string) (*SQLiteClient, error) { + // Add busy timeout param to DSN (milliseconds) + if !strings.Contains(dataSourceName, "_busy_timeout") { + if strings.Contains(dataSourceName, "?") { + dataSourceName += "&_busy_timeout=5000" // 5 seconds + } else { + dataSourceName += "?_busy_timeout=5000" + } + } + db, err := sql.Open("sqlite3", dataSourceName) if err != nil { return nil, fmt.Errorf("error connecting to SQLite: %s", err) @@ -28,6 +37,7 @@ func NewSQLiteClient(dataSourceName string) (*SQLiteClient, error) { return &SQLiteClient{db: db}, nil } + // createTables creates the required tables if they don't exist func createTables(db *sql.DB) error { createSongsTable := ` @@ -100,22 +110,26 @@ func (db *SQLiteClient) GetCouples(addresses []uint32) (map[uint32][]models.Coup if err != nil { return nil, fmt.Errorf("error querying database: %s", err) } - defer rows.Close() var docCouples []models.Couple for rows.Next() { var couple models.Couple if err := rows.Scan(&couple.AnchorTimeMs, &couple.SongID); err != nil { + rows.Close() // close before returning error return nil, fmt.Errorf("error scanning row: %s", err) } docCouples = append(docCouples, couple) } + + rows.Close() // close explicitly after reading + couples[address] = docCouples } return couples, nil } + func (db *SQLiteClient) TotalSongs() (int, error) { var count int err := db.db.QueryRow("SELECT COUNT(*) FROM songs").Scan(&count)