Skip to content

Commit

Permalink
feat: add support for read-only transactions in TransactionOptions (#320
Browse files Browse the repository at this point in the history
)

* Add new typesafe builders for read-only `TransactionOptions.readOnlyOptionsBuilder` and read-write `TransactionOptions.readWriteOptionsBuilder` transactions in TransactionOptions
  * These new builders ensure only those parameters relevant to the respective type of transaction are available
* Deprecate existing `TransactionOptions.create(...)` methods in favor of the new builders
* Update Transaction and TransactionRunner to use TransactionOptions directly
  • Loading branch information
BenWhitehead committed Aug 12, 2020
1 parent 01f4c69 commit c25dca3
Show file tree
Hide file tree
Showing 7 changed files with 463 additions and 39 deletions.
6 changes: 6 additions & 0 deletions google-cloud-firestore/pom.xml
Expand Up @@ -152,6 +152,12 @@
<version>2.11.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
<scope>test</scope>
</dependency>
</dependencies>

<reporting>
Expand Down
Expand Up @@ -30,7 +30,6 @@
import com.google.firestore.v1.BatchGetDocumentsResponse;
import com.google.firestore.v1.DatabaseRootName;
import com.google.protobuf.ByteString;
import io.grpc.Context;
import io.opencensus.trace.AttributeValue;
import io.opencensus.trace.Tracer;
import io.opencensus.trace.Tracing;
Expand All @@ -40,7 +39,6 @@
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Executor;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

Expand Down Expand Up @@ -310,15 +308,9 @@ public <T> ApiFuture<T> runAsyncTransaction(
public <T> ApiFuture<T> runAsyncTransaction(
@Nonnull final Transaction.AsyncFunction<T> updateFunction,
@Nonnull TransactionOptions transactionOptions) {
final Executor userCallbackExecutor =
Context.currentContextExecutor(
transactionOptions.getExecutor() != null
? transactionOptions.getExecutor()
: firestoreClient.getExecutor());

TransactionRunner<T> transactionRunner =
new TransactionRunner<>(
this, updateFunction, userCallbackExecutor, transactionOptions.getNumberOfAttempts());
new TransactionRunner<>(this, updateFunction, transactionOptions);
return transactionRunner.run();
}

Expand Down
Expand Up @@ -19,11 +19,13 @@
import com.google.api.core.ApiFunction;
import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutures;
import com.google.cloud.firestore.TransactionOptions.TransactionOptionsType;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.firestore.v1.BeginTransactionRequest;
import com.google.firestore.v1.BeginTransactionResponse;
import com.google.firestore.v1.RollbackRequest;
import com.google.firestore.v1.TransactionOptions.ReadOnly;
import com.google.protobuf.ByteString;
import com.google.protobuf.Empty;
import java.util.List;
Expand Down Expand Up @@ -61,12 +63,18 @@ public interface AsyncFunction<T> {
ApiFuture<T> updateCallback(Transaction transaction);
}

private final TransactionOptions transactionOptions;
@Nullable private final ByteString previousTransactionId;
private ByteString transactionId;
private @Nullable ByteString previousTransactionId;

Transaction(FirestoreImpl firestore, @Nullable Transaction previousTransaction) {
Transaction(
FirestoreImpl firestore,
TransactionOptions transactionOptions,
@Nullable Transaction previousTransaction) {
super(firestore);
previousTransactionId = previousTransaction != null ? previousTransaction.transactionId : null;
this.transactionOptions = transactionOptions;
this.previousTransactionId =
previousTransaction != null ? previousTransaction.transactionId : null;
}

Transaction wrapResult(ApiFuture<WriteResult> result) {
Expand All @@ -78,11 +86,18 @@ ApiFuture<Void> begin() {
BeginTransactionRequest.Builder beginTransaction = BeginTransactionRequest.newBuilder();
beginTransaction.setDatabase(firestore.getDatabaseName());

if (previousTransactionId != null) {
if (TransactionOptionsType.READ_WRITE.equals(transactionOptions.getType())
&& previousTransactionId != null) {
beginTransaction
.getOptionsBuilder()
.getReadWriteBuilder()
.setRetryTransaction(previousTransactionId);
} else if (TransactionOptionsType.READ_ONLY.equals(transactionOptions.getType())) {
final ReadOnly.Builder readOnlyBuilder = ReadOnly.newBuilder();
if (transactionOptions.getReadTime() != null) {
readOnlyBuilder.setReadTime(transactionOptions.getReadTime());
}
beginTransaction.getOptionsBuilder().setReadOnly(readOnlyBuilder);
}

ApiFuture<BeginTransactionResponse> transactionBeginFuture =
Expand Down

0 comments on commit c25dca3

Please sign in to comment.