Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

rollback on panic #119

Merged
merged 2 commits into from Dec 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 19 additions & 10 deletions crdb/common.go
Expand Up @@ -39,15 +39,23 @@ type Tx interface {
// fn is subject to the same restrictions as the fn passed to ExecuteTx.
func ExecuteInTx(ctx context.Context, tx Tx, fn func() error) (err error) {
defer func() {
if err == nil {
r := recover()

if r == nil && err == nil {
// Ignore commit errors. The tx has already been committed by RELEASE.
_ = tx.Commit(ctx)
} else {
// We always need to execute a Rollback() so sql.DB releases the
// connection.
_ = tx.Rollback(ctx)
return
}

// We always need to execute a Rollback() so sql.DB releases the
// connection.
_ = tx.Rollback(ctx)

if r != nil {
panic(r)
}
}()

// Specify that we intend to retry this txn in case of CockroachDB retryable
// errors.
if err = tx.Exec(ctx, "SAVEPOINT cockroach_restart"); err != nil {
Expand All @@ -58,26 +66,27 @@ func ExecuteInTx(ctx context.Context, tx Tx, fn func() error) (err error) {
const maxRetries = 50
retryCount := 0
for {
released := false
releaseFailed := false
err = fn()
if err == nil {
// RELEASE acts like COMMIT in CockroachDB. We use it since it gives us an
// opportunity to react to retryable errors, whereas tx.Commit() doesn't.
released = true
if err = tx.Exec(ctx, "RELEASE SAVEPOINT cockroach_restart"); err == nil {
return nil
}
releaseFailed = true
}

// We got an error; let's see if it's a retryable one and, if so, restart.
if !errIsRetryable(err) {
if released {
if releaseFailed {
err = newAmbiguousCommitError(err)
}
return err
}

if retryErr := tx.Exec(ctx, "ROLLBACK TO SAVEPOINT cockroach_restart"); retryErr != nil {
return newTxnRestartError(retryErr, err)
if rollbackErr := tx.Exec(ctx, "ROLLBACK TO SAVEPOINT cockroach_restart"); rollbackErr != nil {
return newTxnRestartError(rollbackErr, err)
}

retryCount++
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -3,7 +3,7 @@ module github.com/cockroachdb/cockroach-go/v2
go 1.13

require (
github.com/gofrs/flock v0.8.1 // indirect
github.com/gofrs/flock v0.8.1
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just from go mod download; go mod tidy on my machine, happy to revert if I got it wrong.

github.com/jackc/pgx/v4 v4.10.1
github.com/jmoiron/sqlx v1.3.1
github.com/lib/pq v1.10.0
Expand Down