1
0
Fork 0

Clearer control for busy timeout

master
Philip O'Toole 8 months ago
parent d39c0c8367
commit 240fb86e13

@ -320,6 +320,22 @@ func (db *DB) WALSize() (int64, error) {
return 0, err return 0, err
} }
// SetBusyTimeout sets the busy timeout for the database.
func (db *DB) SetBusyTimeout(ms int) error {
_, err := db.rwDB.Exec(fmt.Sprintf("PRAGMA busy_timeout=%d", ms))
return err
}
// BusyTimeout returns the current busy timeout value.
func (db *DB) BusyTimeout() (int, error) {
var rwN int
err := db.rwDB.QueryRow("PRAGMA busy_timeout").Scan(&rwN)
if err != nil {
return 0, err
}
return rwN, err
}
// Checkpoint checkpoints the WAL file. If the WAL file is not enabled, this // Checkpoint checkpoints the WAL file. If the WAL file is not enabled, this
// function is a no-op. // function is a no-op.
func (db *DB) Checkpoint(mode CheckpointMode) error { func (db *DB) Checkpoint(mode CheckpointMode) error {
@ -342,11 +358,16 @@ func (db *DB) CheckpointWithTimeout(mode CheckpointMode, dur time.Duration) (err
}() }()
if dur > 0 { if dur > 0 {
if _, err := db.rwDB.Exec(fmt.Sprintf("PRAGMA busy_timeout=%d", dur.Milliseconds())); err != nil { bt, err := db.BusyTimeout()
if err != nil {
return fmt.Errorf("failed to get busy_timeout on checkpointing connection: %s", err.Error())
}
if err := db.SetBusyTimeout(int(dur.Milliseconds())); err != nil {
return fmt.Errorf("failed to set busy_timeout on checkpointing connection: %s", err.Error()) return fmt.Errorf("failed to set busy_timeout on checkpointing connection: %s", err.Error())
} }
defer func() { defer func() {
if _, err := db.rwDB.Exec("PRAGMA busy_timeout=5000"); err != nil { // Reset back to default
if _, err := db.rwDB.Exec(fmt.Sprintf("PRAGMA busy_timeout=%d", bt)); err != nil {
db.logger.Printf("failed to reset busy_timeout on checkpointing connection: %s", err.Error()) db.logger.Printf("failed to reset busy_timeout on checkpointing connection: %s", err.Error())
} }
}() }()

@ -2,14 +2,44 @@ package db
import ( import (
"errors" "errors"
"fmt"
"os" "os"
"strings" "strings"
"testing" "testing"
command "github.com/rqlite/rqlite/v8/command/proto" command "github.com/rqlite/rqlite/v8/command/proto"
"github.com/rqlite/rqlite/v8/random"
"github.com/rqlite/rqlite/v8/testdata/chinook" "github.com/rqlite/rqlite/v8/testdata/chinook"
) )
func testBusyTimeout(t *testing.T, db *DB) {
rbt := random.Intn(10000)
_, err := db.ExecuteStringStmt(fmt.Sprintf("PRAGMA busy_timeout=%d", rbt))
if err != nil {
t.Fatalf("failed to set busy_timeout: %s", err.Error())
}
bt, err := db.BusyTimeout()
if err != nil {
t.Fatalf("failed to get busy_timeout: %s", err.Error())
}
if exp, got := rbt, bt; exp != got {
t.Fatalf("expected busy_timeout %d, got %d", exp, got)
}
rbt2 := random.Intn(10000)
if err := db.SetBusyTimeout(rbt2); err != nil {
t.Fatalf("failed to set busy_timeout: %s", err.Error())
}
bt, err = db.BusyTimeout()
if err != nil {
t.Fatalf("failed to get busy_timeout: %s", err.Error())
}
if exp, got := rbt2, bt; exp != got {
t.Fatalf("expected busy_timeout %d, got %d", exp, got)
}
}
func testCompileOptions(t *testing.T, db *DB) { func testCompileOptions(t *testing.T, db *DB) {
_, err := db.CompileOptions() _, err := db.CompileOptions()
if err != nil { if err != nil {
@ -1529,6 +1559,7 @@ func Test_DatabaseCommonOperations(t *testing.T) {
name string name string
testFunc func(*testing.T, *DB) testFunc func(*testing.T, *DB)
}{ }{
{"BusyTimeout", testBusyTimeout},
{"SetSynchronousMode", testSetSynchronousMode}, {"SetSynchronousMode", testSetSynchronousMode},
{"CompileOptions", testCompileOptions}, {"CompileOptions", testCompileOptions},
{"TableNotExist", testTableNotExist}, {"TableNotExist", testTableNotExist},

Loading…
Cancel
Save