Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@olavloite
Copy link

Adds ReadWriteTransaction including internal retries if the transaction is aborted. All statements that are executed on a ReadWriteTransaction are recorded internally in the transaction, and a running SHA-256 checksum is kept based on all the query results that are returned to the user. If the transaction is aborted by Cloud Spanner, a retry is automatically started and deemed successful if:

  1. All DML statements return the same update count or the same error as during the original transaction.
  2. All queries that returned an error during the original transaction return the same error during the retry.
  3. The calculated checksums of all the rows that have been consumed of each result set returned by the transaction are equal.

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Jul 26, 2019
@olavloite olavloite requested a review from kolea2 July 26, 2019 18:05
@Override
void checkValidTransaction() {
ConnectionPreconditions.checkState(
state == UnitOfWorkState.STARTED, "This transaction has status " + state.name());
Copy link
Contributor

Choose a reason for hiding this comment

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

Would slightly change the precondition message to add acceptable status

Copy link
Author

Choose a reason for hiding this comment

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

done

}

/** Create a pseudo COMMIT statement to allow it to be cancelled or time out. */
private final ParsedStatement commitStatement =
Copy link
Contributor

Choose a reason for hiding this comment

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

sorry, could you explain what this does?

Copy link
Author

Choose a reason for hiding this comment

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

I've added the following javadoc to the field:

  /**
   * Create a COMMIT statement to use with the {@link #commit()} method to allow it to be
   * cancelled, time out or retried.
   *
   * {@link ReadWriteTransaction} uses the generic methods
   * {@link #executeAsync(ParsedStatement, Callable)} and {@link #runWithRetry(Callable)} to
   * allow statements to be cancelled, to timeout and to be retried. These methods require a
   * {@link ParsedStatement} as input. When the {@link #commit()} method is called directly, we do
   * not have a {@link ParsedStatement}, and the method uses this statement instead in order to use
   * the same logic as the other statements.
   */

// In case the transaction manager didn't pick up the abort correctly, we'll rollback
// manually and do another try. This seems to be the case if the transaction was
// aborted and txContext.executeUpdate(Statement) is called.
// TODO: Check whether TransactionContextImpl.executeUpdate(Statement) handles
Copy link
Contributor

Choose a reason for hiding this comment

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

do we still need this TODO?

Copy link
Author

@olavloite olavloite Jul 30, 2019

Choose a reason for hiding this comment

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

No, this related to a bug that was in the Spanner client library when the initial copy to the private repo was made. It has long been fixed (and if not, it will be picked up by a test case, as that was how it was found in the first place).
It's removed.

for (RetriableStatement statement : statements) {
statement.retry(aborted);
}
successfulRetries++;
Copy link
Contributor

Choose a reason for hiding this comment

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

should this be in the loop, or is it per batch of statements?

Copy link
Author

Choose a reason for hiding this comment

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

It is per successful retry of an entire transaction, i.e. per batch of statements, so it should be outside of the loop.

@olavloite olavloite force-pushed the spanner-jdbc-21-read-write-tx branch from 53fbe74 to bb61b31 Compare July 30, 2019 06:00
@olavloite olavloite requested a review from kolea2 July 30, 2019 06:00
if (retryAbortsInternally) {
return asyncExecuteStatement(
statement,
new Callable<ResultSet>() {
Copy link
Contributor

Choose a reason for hiding this comment

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

minor - can address in a future PR: let's extract out the Callable into a descriptive variable

@olavloite olavloite merged commit f80c200 into googleapis:spanner-jdbc Jul 30, 2019
olavloite added a commit to olavloite/google-cloud-java that referenced this pull request Aug 5, 2019
* add ReadWriteTransaction

* refactor inner classes to separate files

* included allowed state to error msg

* added javadoc to the COMMIT and RUN BATCH statements

* removed todo no longer needed in public repo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla: yes This human has signed the Contributor License Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants