db: retry on sqlite locked error

Since we are using the shared cache with the lock notify we won't receive
SQLITE_BUSY errors but we could receive SQLITE_LOCKED errors due to deadlocks or
locked tables on concurrent read and write transactions.

This patch catches this kind of errors and retries the tx until maxTxRetries.
This commit is contained in:
Simone Gotti 2019-07-24 12:16:43 +02:00
parent 77ee8d9e7d
commit 3297244d5d
1 changed files with 22 additions and 1 deletions

View File

@ -20,7 +20,7 @@ import (
"regexp"
"time"
_ "github.com/mattn/go-sqlite3"
"github.com/mattn/go-sqlite3"
errors "golang.org/x/xerrors"
)
@ -29,6 +29,8 @@ type Type string
const (
Sqlite3 Type = "sqlite3"
Postgres Type = "postgres"
maxTxRetries = 20
)
type dbData struct {
@ -171,6 +173,25 @@ func (db *DB) NewTx() (*Tx, error) {
}
func (db *DB) Do(f func(tx *Tx) error) error {
retries := 0
for {
err := db.do(f)
if err != nil {
var sqerr sqlite3.Error
if errors.As(err, &sqerr) {
if sqerr.Code == sqlite3.ErrLocked {
retries++
if retries <= maxTxRetries {
continue
}
}
}
}
return err
}
}
func (db *DB) do(f func(tx *Tx) error) error {
tx, err := db.NewTx()
if err != nil {
return err