1
0
Fork 0

Merge pull request #1646 from rqlite/better-busy-timeout-diag

Expose BUSY TIMEOUT on /status
master
Philip O'Toole 8 months ago committed by GitHub
commit b1e978b42a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,3 +1,7 @@
## 8.18.5 (unreleased)
### Implementation changes and bug fixes
- [PR #1644](https://github.com/rqlite/rqlite/pull/1644): Expose BUSY TIMEOUT on /status.
## 8.18.4 (January 30th 2024)
### Implementation changes and bug fixes
- [PR #1644](https://github.com/rqlite/rqlite/pull/1644): Remove an unnecessary memcpy during Snapshotting.

@ -321,20 +321,35 @@ func (db *DB) WALSize() (int64, error) {
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
// SetBusyTimeout sets the busy timeout for the database. If a timeout is
// is less than zero it is not set.
func (db *DB) SetBusyTimeout(rwMs, roMs int) (err error) {
if rwMs >= 0 {
_, err := db.rwDB.Exec(fmt.Sprintf("PRAGMA busy_timeout=%d", rwMs))
if err != nil {
return err
}
}
if roMs >= 0 {
_, err = db.roDB.Exec(fmt.Sprintf("PRAGMA busy_timeout=%d", roMs))
if err != nil {
return err
}
}
return nil
}
// 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)
func (db *DB) BusyTimeout() (rwMs, roMs int, err error) {
err = db.rwDB.QueryRow("PRAGMA busy_timeout").Scan(&rwMs)
if err != nil {
return 0, err
return 0, 0, err
}
return rwN, err
err = db.rwDB.QueryRow("PRAGMA busy_timeout").Scan(&roMs)
if err != nil {
return 0, 0, err
}
return rwMs, roMs, nil
}
// Checkpoint checkpoints the WAL file. If the WAL file is not enabled, this
@ -359,16 +374,16 @@ func (db *DB) CheckpointWithTimeout(mode CheckpointMode, dur time.Duration) (err
}()
if dur > 0 {
bt, err := db.BusyTimeout()
rwBt, _, 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 {
if err := db.SetBusyTimeout(int(dur.Milliseconds()), -1); err != nil {
return fmt.Errorf("failed to set busy_timeout on checkpointing connection: %s", err.Error())
}
defer func() {
// Reset back to default
if _, err := db.rwDB.Exec(fmt.Sprintf("PRAGMA busy_timeout=%d", bt)); err != nil {
if err := db.SetBusyTimeout(rwBt, -1); err != nil {
db.logger.Printf("failed to reset busy_timeout on checkpointing connection: %s", err.Error())
}
}()
@ -1115,6 +1130,7 @@ func (db *DB) pragmas() (map[string]interface{}, error) {
"journal_mode",
"foreign_keys",
"wal_autocheckpoint",
"busy_timeout",
} {
var s string
if err := v.QueryRow(fmt.Sprintf("PRAGMA %s", p)).Scan(&s); err != nil {

@ -19,23 +19,23 @@ func testBusyTimeout(t *testing.T, db *DB) {
t.Fatalf("failed to set busy_timeout: %s", err.Error())
}
bt, err := db.BusyTimeout()
rw, _, err := db.BusyTimeout()
if err != nil {
t.Fatalf("failed to get busy_timeout: %s", err.Error())
}
if exp, got := rbt, bt; exp != got {
if exp, got := rbt, rw; exp != got {
t.Fatalf("expected busy_timeout %d, got %d", exp, got)
}
rbt2 := random.Intn(10000)
if err := db.SetBusyTimeout(rbt2); err != nil {
rw2 := random.Intn(10000)
if err := db.SetBusyTimeout(rw2, 0); err != nil {
t.Fatalf("failed to set busy_timeout: %s", err.Error())
}
bt, err = db.BusyTimeout()
rw, _, err = db.BusyTimeout()
if err != nil {
t.Fatalf("failed to get busy_timeout: %s", err.Error())
}
if exp, got := rbt2, bt; exp != got {
if exp, got := rw2, rw; exp != got {
t.Fatalf("expected busy_timeout %d, got %d", exp, got)
}
}

@ -30,8 +30,8 @@ class TestSingleNode(unittest.TestCase):
n = self.cluster.wait_for_leader()
ro_pragmas = n.pragmas()['ro']
rw_pragmas = n.pragmas()['rw']
self.assertEqual(ro_pragmas, d_("{'foreign_keys': '0', 'journal_mode': 'wal', 'synchronous': '0', 'wal_autocheckpoint': '1000'}"))
self.assertEqual(rw_pragmas, d_("{'foreign_keys': '0', 'journal_mode': 'wal', 'synchronous': '0', 'wal_autocheckpoint': '0'}"))
self.assertEqual(ro_pragmas, d_("{'busy_timeout': '5000', 'foreign_keys': '0', 'journal_mode': 'wal', 'synchronous': '0', 'wal_autocheckpoint': '1000'}"))
self.assertEqual(rw_pragmas, d_("{'busy_timeout': '5000', 'foreign_keys': '0', 'journal_mode': 'wal', 'synchronous': '0', 'wal_autocheckpoint': '0'}"))
def test_simple_raw_queries(self):
'''Test simple queries work as expected'''

Loading…
Cancel
Save