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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(spanner): fix mutation only case in rw mux with aborted error #3571

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

harshachinta
Copy link
Contributor

@harshachinta harshachinta commented Dec 26, 2024

This PR fixes the following scenario.

In a mutation-only scenario for a read-write transaction using multiplexed sessions, an explicit BeginTransaction RPC is triggered after the user operation completes.

However, if an ABORT occurs during this BeginTransaction RPC, the client retry mechanism performs an explicit BeginTransaction before the user operation begins. This behavior causes issues in multiplexed sessions because, in mutation-only cases, the BeginTransaction requires a mutation key to generate a precommit token. This precommit token is essential for committing the transaction.

Currently, since the BeginTransaction during a retry is executed before the user operation, no mutation key is available, and consequently, no precommit token is included in the transaction response. This leads to commit failures with an error as shown below

com.google.cloud.spanner.SpannerException: INVALID_ARGUMENT: io.grpc.StatusRuntimeException: INVALID_ARGUMENT: A Commit request for a read-write transaction on a multiplexed session must specify a precommit token.

The fix involves performing a BeginTransaction RPC for mutation-only cases with multiplexed sessions after the user operation completes, regardless of whether it is an initial operation or a retry.

@harshachinta harshachinta requested a review from a team as a code owner December 26, 2024 12:38
@product-auto-label product-auto-label bot added size: l Pull request size is large. api: spanner Issues related to the googleapis/java-spanner API. labels Dec 26, 2024
@harshachinta harshachinta changed the title chore(spanner): fix mutation only case ibn rw using mux with aborted … chore(spanner): fix mutation only case inn rw using mux with aborted … Dec 26, 2024
@harshachinta harshachinta changed the title chore(spanner): fix mutation only case inn rw using mux with aborted … chore(spanner): fix mutation only case in rw using mux with aborted … Dec 26, 2024
@harshachinta harshachinta changed the title chore(spanner): fix mutation only case in rw using mux with aborted … chore(spanner): fix mutation only case in rw mux with aborted error Dec 26, 2024
@olavloite
Copy link
Collaborator

However, if an ABORT occurs during this BeginTransaction RPC

Is this something that can actually happen?

the mutations are not sent, and the precommit token is not received, resulting in
an INVALID_ARGUMENT error (missing precommit token) during commit.
*/
useInlinedBegin = txn.mutationsOnlyTransaction || txn.transactionId != null;
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: maybe we should rename this variable to something like shouldEnsureTxnAtStart? Now this variable is being set to true for a case that never uses inlinedBegin, which could cause confusion to new engineers who read this code for the first time.

@@ -83,6 +83,7 @@ public class SessionPoolOptions {

// TODO: Change to use java.time.Duration.
private final Duration multiplexedSessionMaintenanceDuration;
private final boolean skipVerifyingBeginTransactionForMuxRW;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this temporary just to be able to test with/without this fix?

Comment on lines +1301 to +1302
// request
// and precommit token is set in Commit request.
Copy link
Collaborator

Choose a reason for hiding this comment

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

super-nit: fix formatting

Comment on lines +1321 to +1322
// is cleared
// after the first call, so the retry should succeed.
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: fix formatting

Comment on lines +1368 to +1380
Spanner spanner1 =
SpannerOptions.newBuilder()
.setProjectId("test-project")
.setChannelProvider(channelProvider)
.setCredentials(NoCredentials.getInstance())
.setSessionPoolOption(
SessionPoolOptions.newBuilder()
.setUseMultiplexedSession(true)
.setUseMultiplexedSessionForRW(true)
.setSkipVerifyingBeginTransactionForMuxRW(true)
.build())
.build()
.getService();
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: it seems like a very large part of these tests are equal (e.g. setting up Spanner and verifying the requests). Can we combine those parts into shared methods that are used by the various test methods?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: spanner Issues related to the googleapis/java-spanner API. size: l Pull request size is large.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants