Reuse opened session in the context (#44939)

This commit is contained in:
Yuriy Tseretyan
2022-02-08 09:02:23 -05:00
committed by GitHub
parent 67a3e1d6fd
commit 6a7a486c6f
3 changed files with 96 additions and 15 deletions

View File

@@ -3,13 +3,15 @@ package sqlstore
import (
"context"
"errors"
"fmt"
"time"
"github.com/mattn/go-sqlite3"
"xorm.io/xorm"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/util/errutil"
"github.com/mattn/go-sqlite3"
"xorm.io/xorm"
)
var tsclogger = log.New("sqlstore.transactions")
@@ -35,15 +37,28 @@ func inTransactionWithRetry(callback DBTransactionFunc, retry int) error {
}
func inTransactionWithRetryCtx(ctx context.Context, engine *xorm.Engine, callback DBTransactionFunc, retry int) error {
sess, err := startSession(ctx, engine, true)
sess, isNew, err := startSessionOrUseExisting(ctx, engine, true)
if err != nil {
return err
}
defer sess.Close()
if !sess.transactionOpen && !isNew {
// this should not happen because the only place that creates reusable session begins a new transaction.
return fmt.Errorf("cannot reuse existing session that did not start transaction")
}
if isNew { // if this call initiated the session, it should be responsible for closing it.
defer sess.Close()
}
err = callback(sess)
if !isNew {
tsclogger.Debug("skip committing the transaction because it belongs to a session created in the outer scope")
// Do not commit the transaction if the session was reused.
return err
}
// special handling of database locked errors for sqlite, then we can retry 5 times
var sqlError sqlite3.Error
if errors.As(err, &sqlError) && retry < 5 && (sqlError.Code == sqlite3.ErrLocked || sqlError.Code == sqlite3.ErrBusy) {