Fix error handling when DB.init() fails
The `DB.init()` can fail temporarily for a variety of reasons such as the database being locked. Previously, the DB would save the `*sql.DB` connection even if a step failed and this prevented the database from attempting initialization again. This change makes it so that the connection is only saved if initialization is successful. On failure, the initialization process will be retried on next sync.
This commit is contained in:
21
db.go
21
db.go
@@ -381,11 +381,28 @@ func (db *DB) init() (err error) {
|
|||||||
dsn := db.path
|
dsn := db.path
|
||||||
dsn += fmt.Sprintf("?_busy_timeout=%d", BusyTimeout.Milliseconds())
|
dsn += fmt.Sprintf("?_busy_timeout=%d", BusyTimeout.Milliseconds())
|
||||||
|
|
||||||
// Connect to SQLite database & enable WAL.
|
// Connect to SQLite database.
|
||||||
if db.db, err = sql.Open("sqlite3", dsn); err != nil {
|
if db.db, err = sql.Open("sqlite3", dsn); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if _, err := db.db.Exec(`PRAGMA journal_mode = wal;`); err != nil {
|
}
|
||||||
|
|
||||||
|
// Ensure database is closed if init fails.
|
||||||
|
// Initialization can retry on next sync.
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
db.releaseReadLock()
|
||||||
|
db.db.Close()
|
||||||
|
db.db = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Enable WAL and ensure it is set. New mode should be returned on success:
|
||||||
|
// https://www.sqlite.org/pragma.html#pragma_journal_mode
|
||||||
|
var mode string
|
||||||
|
if err := db.db.QueryRow(`PRAGMA journal_mode = wal;`).Scan(&mode); err != nil {
|
||||||
return fmt.Errorf("enable wal: %w", err)
|
return fmt.Errorf("enable wal: %w", err)
|
||||||
|
} else if mode != "wal" {
|
||||||
|
return fmt.Errorf("enable wal failed, mode=%q", mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable autocheckpoint for litestream's connection.
|
// Disable autocheckpoint for litestream's connection.
|
||||||
|
|||||||
Reference in New Issue
Block a user