Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
Go
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253package db
import ( "context" "errors" "time"
"github.com/mattn/go-sqlite3")
const defaultSQLiteRetryBudget = 20 * time.Second
func isSQLiteBusy(err error) bool { var sqliteErr sqlite3.Error if !errors.As(err, &sqliteErr) { return false } return sqliteErr.Code == sqlite3.ErrBusy || sqliteErr.Code == sqlite3.ErrLocked}
func retrySQLite(fn func() error) error { return retrySQLiteCtx(context.Background(), defaultSQLiteRetryBudget, fn)}
func retrySQLiteCtx(ctx context.Context, budget time.Duration, fn func() error) error { if budget <= 0 { budget = defaultSQLiteRetryBudget } deadline := time.Now().Add(budget) backoff := 10 * time.Millisecond const maxBackoff = 100 * time.Millisecond
for { if err := ctx.Err(); err != nil { return err } err := fn() if err == nil || !isSQLiteBusy(err) { return err } if time.Now().After(deadline) { return err }
select { case <-ctx.Done(): return ctx.Err() case <-time.After(backoff): } backoff = min(backoff*2, maxBackoff) }}