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:
parent
77ee8d9e7d
commit
3297244d5d
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue