Skip to content

Commit 23f6ea6

Browse files
committed
Merge branch 'pull-retry-aborts' into spanner-lib
2 parents 928ee4d + 0e5ac05 commit 23f6ea6

File tree

4 files changed

+43
-31
lines changed

4 files changed

+43
-31
lines changed

conn.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"errors"
2222
"log/slog"
2323
"slices"
24+
"sync"
2425
"time"
2526

2627
"cloud.google.com/go/spanner"
@@ -368,11 +369,6 @@ func (c *conn) SetRetryAbortsInternally(retry bool) error {
368369
}
369370

370371
func (c *conn) setRetryAbortsInternally(retry bool) (driver.Result, error) {
371-
if c.inTransaction() {
372-
if _, err := c.tx.setRetryAbortsInternally(retry); err != nil {
373-
return nil, err
374-
}
375-
}
376372
if err := propertyRetryAbortsInternally.SetValue(c.state, retry, connectionstate.ContextUser); err != nil {
377373
return nil, err
378374
}
@@ -1195,9 +1191,8 @@ func (c *conn) BeginTx(ctx context.Context, driverOpts driver.TxOptions) (driver
11951191
if c.tempTransactionOptions != nil && c.tempTransactionOptions.close != nil {
11961192
tempCloseFunc = c.tempTransactionOptions.close
11971193
}
1198-
disableInternalRetries := !c.RetryAbortsInternally()
1199-
if c.tempTransactionOptions != nil {
1200-
disableInternalRetries = c.tempTransactionOptions.DisableInternalRetries
1194+
if !disableRetryAborts && c.tempTransactionOptions != nil {
1195+
disableRetryAborts = c.tempTransactionOptions.DisableInternalRetries
12011196
}
12021197

12031198
tx, err := spanner.NewReadWriteStmtBasedTransactionWithCallbackForOptions(ctx, c.client, opts, func() spanner.TransactionOptions {
@@ -1232,7 +1227,9 @@ func (c *conn) BeginTx(ctx context.Context, driverOpts driver.TxOptions) (driver
12321227
}
12331228
},
12341229
// Disable internal retries if any of these options have been set.
1235-
retryAborts: !disableInternalRetries && !disableRetryAborts,
1230+
retryAborts: sync.OnceValue(func() bool {
1231+
return c.RetryAbortsInternally() && !disableRetryAborts
1232+
}),
12361233
}
12371234
c.clearCommitResponse()
12381235
return c.tx, nil

conn_with_mockserver_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/googleapis/go-sql-spanner/connectionstate"
2929
"github.com/googleapis/go-sql-spanner/testutil"
3030
"google.golang.org/grpc/codes"
31+
"google.golang.org/grpc/status"
3132
"google.golang.org/protobuf/proto"
3233
"google.golang.org/protobuf/types/known/anypb"
3334
"google.golang.org/protobuf/types/known/emptypb"
@@ -731,6 +732,35 @@ func TestSetRetryAbortsInternallyInActiveTransaction(t *testing.T) {
731732
_ = tx.Rollback()
732733
}
733734

735+
func TestSetLocalRetryAbortsInternally(t *testing.T) {
736+
t.Parallel()
737+
738+
db, server, teardown := setupTestDBConnection(t)
739+
defer teardown()
740+
ctx := context.Background()
741+
742+
tx, err := db.BeginTx(ctx, &sql.TxOptions{})
743+
if err != nil {
744+
t.Fatal(err)
745+
}
746+
if _, err := tx.ExecContext(ctx, "set local retry_aborts_internally = false"); err != nil {
747+
t.Fatal(err)
748+
}
749+
if _, err := tx.ExecContext(ctx, testutil.UpdateBarSetFoo); err != nil {
750+
t.Fatal(err)
751+
}
752+
// Instruct the mock server to return Aborted when Commit is called.
753+
// This should cause the transaction to fail, and as internal retries have been
754+
// disabled, it should not be retried.
755+
server.TestSpanner.PutExecutionTime(testutil.MethodCommitTransaction, testutil.SimulatedExecutionTime{
756+
Errors: []error{status.Error(codes.Aborted, "Aborted")},
757+
})
758+
err = tx.Commit()
759+
if g, w := spanner.ErrCode(err), codes.Aborted; g != w {
760+
t.Fatalf("error mismatch\n Got: %v\nWant: %v", g, w)
761+
}
762+
}
763+
734764
func TestSetAutocommitDMLMode(t *testing.T) {
735765
t.Parallel()
736766

driver_with_mockserver_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4567,7 +4567,7 @@ func TestRunTransaction(t *testing.T) {
45674567
if g, w := rwTx.ctx, ctx; g != w {
45684568
return fmt.Errorf("getting the transaction through reflection failed")
45694569
}
4570-
if rwTx.retryAborts {
4570+
if rwTx.retryAborts() {
45714571
return fmt.Errorf("internal retries should be disabled during RunTransaction")
45724572
}
45734573

@@ -5028,7 +5028,7 @@ func TestBeginReadWriteTransaction(t *testing.T) {
50285028
if g, w := rwTx.ctx, ctx; g != w {
50295029
t.Fatal("getting the transaction through reflection failed")
50305030
}
5031-
if rwTx.retryAborts {
5031+
if rwTx.retryAborts() {
50325032
t.Fatal("internal retries should be disabled during this transaction")
50335033
}
50345034

transaction.go

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ type contextTransaction interface {
5454
AbortBatch() (driver.Result, error)
5555

5656
BufferWrite(ms []*spanner.Mutation) error
57-
58-
setRetryAbortsInternally(retry bool) (driver.Result, error)
5957
}
6058

6159
type rowIterator interface {
@@ -205,11 +203,6 @@ func (tx *readOnlyTransaction) BufferWrite([]*spanner.Mutation) error {
205203
return spanner.ToSpannerError(status.Errorf(codes.FailedPrecondition, "read-only transactions cannot write"))
206204
}
207205

208-
func (tx *readOnlyTransaction) setRetryAbortsInternally(_ bool) (driver.Result, error) {
209-
// no-op, ignore
210-
return driver.ResultNoRows, nil
211-
}
212-
213206
// ErrAbortedDueToConcurrentModification is returned by a read/write transaction
214207
// that was aborted by Cloud Spanner, and where the internal retry attempt
215208
// failed because it detected that the results during the retry were different
@@ -244,7 +237,7 @@ type readWriteTransaction struct {
244237
close func(result txResult, commitResponse *spanner.CommitResponse, commitErr error)
245238
// retryAborts indicates whether this transaction will automatically retry
246239
// the transaction if it is aborted by Spanner. The default is true.
247-
retryAborts bool
240+
retryAborts func() bool
248241

249242
// statements contains the list of statements that has been executed on this
250243
// transaction so far. These statements will be replayed on a new read write
@@ -415,7 +408,7 @@ func (tx *readWriteTransaction) Commit() (err error) {
415408
}
416409
var commitResponse spanner.CommitResponse
417410
if tx.rwTx != nil {
418-
if !tx.retryAborts {
411+
if !tx.retryAborts() {
419412
ts, err := tx.rwTx.CommitWithReturnResp(tx.ctx)
420413
tx.close(txResultCommit, &ts, err)
421414
return err
@@ -471,7 +464,7 @@ func (tx *readWriteTransaction) Query(ctx context.Context, stmt spanner.Statemen
471464
}
472465
// If internal retries have been disabled, we don't need to keep track of a
473466
// running checksum for all results that we have seen.
474-
if !tx.retryAborts {
467+
if !tx.retryAborts() {
475468
return &readOnlyRowIterator{tx.rwTx.QueryWithOptions(ctx, stmt, execOptions.QueryOptions)}, nil
476469
}
477470

@@ -509,7 +502,7 @@ func (tx *readWriteTransaction) ExecContext(ctx context.Context, stmt spanner.St
509502
return &result{rowsAffected: updateCount}, nil
510503
}
511504

512-
if !tx.retryAborts {
505+
if !tx.retryAborts() {
513506
return execTransactionalDML(ctx, tx.rwTx, stmt, statementInfo, options)
514507
}
515508

@@ -608,7 +601,7 @@ func (tx *readWriteTransaction) runDmlBatch(ctx context.Context) (*result, error
608601
options := tx.batch.options
609602
tx.batch = nil
610603

611-
if !tx.retryAborts {
604+
if !tx.retryAborts() {
612605
affected, err := tx.rwTx.BatchUpdateWithOptions(ctx, statements, options.QueryOptions)
613606
return &result{rowsAffected: sum(affected)}, err
614607
}
@@ -650,11 +643,3 @@ func errorsEqualForRetry(err1, err2 error) bool {
650643
}
651644
return false
652645
}
653-
654-
func (tx *readWriteTransaction) setRetryAbortsInternally(retry bool) (driver.Result, error) {
655-
if tx.active {
656-
return nil, spanner.ToSpannerError(status.Error(codes.FailedPrecondition, "cannot change retry mode while a transaction is active"))
657-
}
658-
tx.retryAborts = retry
659-
return driver.ResultNoRows, nil
660-
}

0 commit comments

Comments
 (0)