@@ -39,15 +39,23 @@ type Tx interface {
3939// fn is subject to the same restrictions as the fn passed to ExecuteTx.
4040func ExecuteInTx (ctx context.Context , tx Tx , fn func () error ) (err error ) {
4141 defer func () {
42- if err == nil {
42+ r := recover ()
43+
44+ if r == nil && err == nil {
4345 // Ignore commit errors. The tx has already been committed by RELEASE.
4446 _ = tx .Commit (ctx )
45- } else {
46- // We always need to execute a Rollback() so sql.DB releases the
47- // connection.
48- _ = tx .Rollback (ctx )
47+ return
48+ }
49+
50+ // We always need to execute a Rollback() so sql.DB releases the
51+ // connection.
52+ _ = tx .Rollback (ctx )
53+
54+ if r != nil {
55+ panic (r )
4956 }
5057 }()
58+
5159 // Specify that we intend to retry this txn in case of CockroachDB retryable
5260 // errors.
5361 if err = tx .Exec (ctx , "SAVEPOINT cockroach_restart" ); err != nil {
@@ -58,31 +66,35 @@ func ExecuteInTx(ctx context.Context, tx Tx, fn func() error) (err error) {
5866 const maxRetries = 50
5967 retryCount := 0
6068 for {
61- released := false
62- err = fn ()
63- if err == nil {
69+ releaseFailed := false
70+ if err = fn (); err == nil {
6471 // RELEASE acts like COMMIT in CockroachDB. We use it since it gives us an
6572 // opportunity to react to retryable errors, whereas tx.Commit() doesn't.
66- released = true
6773 if err = tx .Exec (ctx , "RELEASE SAVEPOINT cockroach_restart" ); err == nil {
6874 return nil
6975 }
76+ releaseFailed = true
7077 }
71- // We got an error; let's see if it's a retryable one and, if so, restart.
78+
79+ // We got an error (i.e. err != nil) if at this point
80+
81+ // Let's see if it's a retryable one and, if so, restart.
7282 if ! errIsRetryable (err ) {
73- if released {
83+ if releaseFailed {
7484 err = newAmbiguousCommitError (err )
7585 }
7686 return err
7787 }
7888
79- if retryErr := tx .Exec (ctx , "ROLLBACK TO SAVEPOINT cockroach_restart" ); retryErr != nil {
80- return newTxnRestartError (retryErr , err )
89+ if rollbackErr := tx .Exec (ctx , "ROLLBACK TO SAVEPOINT cockroach_restart" ); rollbackErr != nil {
90+ err = newTxnRestartError (rollbackErr , err )
91+ return err
8192 }
8293
8394 retryCount ++
8495 if retryCount > maxRetries {
85- return newMaxRetriesExceededError (err , maxRetries )
96+ err = newMaxRetriesExceededError (err , maxRetries )
97+ return err
8698 }
8799 }
88100}
0 commit comments