From 824417b7b925d633b2931d0267d2d6e34c863ac9 Mon Sep 17 00:00:00 2001 From: Nikhil Chennupati Date: Fri, 16 Oct 2026 22:27:09 -0700 Subject: [PATCH 1/2] feat(firestore): add x-goog-is-transaction routing header Attach x-goog-is-transaction header ('true' for transactional RPCs, 'false' for non-transactional RPCs) in GrpcFirestoreRpc. --- .../firestore/spi/v1/GrpcFirestoreRpc.java | 92 ++++- .../spi/v1/GrpcFirestoreRpcTest.java | 318 ++++++++++++++++++ 2 files changed, 398 insertions(+), 12 deletions(-) diff --git a/java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/spi/v1/GrpcFirestoreRpc.java b/java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/spi/v1/GrpcFirestoreRpc.java index 7224a3014bd2..815f2198efbe 100644 --- a/java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/spi/v1/GrpcFirestoreRpc.java +++ b/java-firestore/google-cloud-firestore/src/main/java/com/google/cloud/firestore/spi/v1/GrpcFirestoreRpc.java @@ -16,15 +16,18 @@ package com.google.cloud.firestore.spi.v1; +import com.google.api.core.ApiFuture; import com.google.api.gax.core.BackgroundResource; import com.google.api.gax.core.GaxProperties; import com.google.api.gax.grpc.GrpcCallContext; import com.google.api.gax.grpc.GrpcTransportChannel; import com.google.api.gax.retrying.RetrySettings; +import com.google.api.gax.rpc.ApiCallContext; import com.google.api.gax.rpc.BidiStreamingCallable; import com.google.api.gax.rpc.ClientContext; import com.google.api.gax.rpc.HeaderProvider; import com.google.api.gax.rpc.NoHeaderProvider; +import com.google.api.gax.rpc.ResponseObserver; import com.google.api.gax.rpc.ServerStreamingCallable; import com.google.api.gax.rpc.TransportChannel; import com.google.api.gax.rpc.UnaryCallable; @@ -41,6 +44,9 @@ import com.google.cloud.firestore.v1.stub.GrpcFirestoreStub; import com.google.cloud.grpc.GrpcTransportOptions; import com.google.cloud.grpc.GrpcTransportOptions.ExecutorFactory; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.firestore.v1.BatchGetDocumentsRequest; import com.google.firestore.v1.BatchGetDocumentsResponse; import com.google.firestore.v1.BatchWriteRequest; @@ -70,6 +76,7 @@ import java.util.Collections; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; /** * GRPC client implementation of the Firestore RPC methods. Exposes FirestoreOptions on top of the @@ -77,6 +84,14 @@ */ public class GrpcFirestoreRpc implements FirestoreRpc { + private static final ApiCallContext TRANSACTION_CALL_CONTEXT = + GrpcCallContext.createDefault() + .withExtraHeaders(ImmutableMap.of("x-goog-is-transaction", ImmutableList.of("true"))); + + private static final ApiCallContext NON_TRANSACTION_CALL_CONTEXT = + GrpcCallContext.createDefault() + .withExtraHeaders(ImmutableMap.of("x-goog-is-transaction", ImmutableList.of("false"))); + private final FirestoreStub firestoreStub; private final ScheduledExecutorService executor; private final ExecutorFactory executorFactory; @@ -84,6 +99,14 @@ public class GrpcFirestoreRpc implements FirestoreRpc { private boolean closed; + @VisibleForTesting + GrpcFirestoreRpc(FirestoreStub firestoreStub) { + this.firestoreStub = firestoreStub; + this.executor = null; + this.executorFactory = null; + this.clientContext = null; + } + public GrpcFirestoreRpc(final FirestoreOptions options) throws IOException { GrpcTransportOptions transportOptions = (GrpcTransportOptions) options.getTransportOptions(); executorFactory = transportOptions.getExecutorFactory(); @@ -221,69 +244,114 @@ public ScheduledExecutorService getExecutor() { @Override public UnaryCallable commitCallable() { - return firestoreStub.commitCallable(); + return withRoutingHeaders( + firestoreStub.commitCallable(), req -> !req.getTransaction().isEmpty()); } @Override public UnaryCallable batchWriteCallable() { - return firestoreStub.batchWriteCallable(); + return firestoreStub.batchWriteCallable().withDefaultCallContext(NON_TRANSACTION_CALL_CONTEXT); } @Override public ServerStreamingCallable batchGetDocumentsCallable() { - return firestoreStub.batchGetDocumentsCallable(); + return withRoutingHeaders( + firestoreStub.batchGetDocumentsCallable(), + req -> !req.getTransaction().isEmpty() || req.hasNewTransaction()); } @Override public ServerStreamingCallable runQueryCallable() { - return firestoreStub.runQueryCallable(); + return withRoutingHeaders( + firestoreStub.runQueryCallable(), + req -> !req.getTransaction().isEmpty() || req.hasNewTransaction()); } @Override public ServerStreamingCallable executePipelineCallable() { - return firestoreStub.executePipelineCallable(); + return withRoutingHeaders( + firestoreStub.executePipelineCallable(), + req -> !req.getTransaction().isEmpty() || req.hasNewTransaction()); } @Override public ServerStreamingCallable runAggregationQueryCallable() { - return firestoreStub.runAggregationQueryCallable(); + return withRoutingHeaders( + firestoreStub.runAggregationQueryCallable(), + req -> !req.getTransaction().isEmpty() || req.hasNewTransaction()); } @Override public UnaryCallable beginTransactionCallable() { - return firestoreStub.beginTransactionCallable(); + return firestoreStub + .beginTransactionCallable() + .withDefaultCallContext(TRANSACTION_CALL_CONTEXT); } @Override public UnaryCallable rollbackCallable() { - return firestoreStub.rollbackCallable(); + return firestoreStub.rollbackCallable().withDefaultCallContext(TRANSACTION_CALL_CONTEXT); } @Override public UnaryCallable listCollectionIdsPagedCallable() { - return firestoreStub.listCollectionIdsPagedCallable(); + return firestoreStub + .listCollectionIdsPagedCallable() + .withDefaultCallContext(NON_TRANSACTION_CALL_CONTEXT); } @Override public UnaryCallable partitionQueryPagedCallable() { - return firestoreStub.partitionQueryPagedCallable(); + return firestoreStub + .partitionQueryPagedCallable() + .withDefaultCallContext(NON_TRANSACTION_CALL_CONTEXT); } @Override public UnaryCallable listDocumentsPagedCallable() { - return firestoreStub.listDocumentsPagedCallable(); + return withRoutingHeaders( + firestoreStub.listDocumentsPagedCallable(), req -> !req.getTransaction().isEmpty()); } @Override public BidiStreamingCallable listenCallable() { - return firestoreStub.listenCallable(); + return firestoreStub.listenCallable().withDefaultCallContext(NON_TRANSACTION_CALL_CONTEXT); + } + + private static UnaryCallable withRoutingHeaders( + UnaryCallable callable, Predicate isTransaction) { + return new UnaryCallable() { + @Override + public ApiFuture futureCall(RequestT request, ApiCallContext thisCallContext) { + ApiCallContext defaultContext = + isTransaction.test(request) ? TRANSACTION_CALL_CONTEXT : NON_TRANSACTION_CALL_CONTEXT; + return callable.futureCall(request, defaultContext.merge(thisCallContext)); + } + }; + } + + private static + ServerStreamingCallable withRoutingHeaders( + ServerStreamingCallable callable, + Predicate isTransaction) { + return new ServerStreamingCallable() { + @Override + public void call( + RequestT request, + ResponseObserver responseObserver, + ApiCallContext thisCallContext) { + ApiCallContext defaultContext = + isTransaction.test(request) ? TRANSACTION_CALL_CONTEXT : NON_TRANSACTION_CALL_CONTEXT; + callable.call(request, responseObserver, defaultContext.merge(thisCallContext)); + } + }; } // This class is needed solely to get access to protected method setInternalHeaderProvider() diff --git a/java-firestore/google-cloud-firestore/src/test/java/com/google/cloud/firestore/spi/v1/GrpcFirestoreRpcTest.java b/java-firestore/google-cloud-firestore/src/test/java/com/google/cloud/firestore/spi/v1/GrpcFirestoreRpcTest.java index 3cf7025d0ffc..e3f8d28b6e65 100644 --- a/java-firestore/google-cloud-firestore/src/test/java/com/google/cloud/firestore/spi/v1/GrpcFirestoreRpcTest.java +++ b/java-firestore/google-cloud-firestore/src/test/java/com/google/cloud/firestore/spi/v1/GrpcFirestoreRpcTest.java @@ -17,18 +17,32 @@ package com.google.cloud.firestore.spi.v1; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import com.google.api.core.ApiFuture; +import com.google.api.core.ApiFutures; +import com.google.api.gax.grpc.GrpcCallContext; import com.google.api.gax.retrying.ExponentialRetryAlgorithm; import com.google.api.gax.retrying.RetryAlgorithm; import com.google.api.gax.retrying.RetrySettings; import com.google.api.gax.retrying.ScheduledRetryingExecutor; +import com.google.api.gax.rpc.ApiCallContext; +import com.google.api.gax.rpc.BidiStreamingCallable; +import com.google.api.gax.rpc.ClientStream; +import com.google.api.gax.rpc.ClientStreamReadyObserver; import com.google.api.gax.rpc.PagedCallSettings; +import com.google.api.gax.rpc.ResponseObserver; import com.google.api.gax.rpc.ServerStreamingCallSettings; +import com.google.api.gax.rpc.ServerStreamingCallable; import com.google.api.gax.rpc.StatusCode.Code; import com.google.api.gax.rpc.UnaryCallSettings; +import com.google.api.gax.rpc.UnaryCallable; import com.google.cloud.firestore.FirestoreOptions; +import com.google.cloud.firestore.v1.FirestoreClient.ListCollectionIdsPagedResponse; import com.google.cloud.firestore.v1.FirestoreClient.ListDocumentsPagedResponse; import com.google.cloud.firestore.v1.FirestoreClient.PartitionQueryPagedResponse; +import com.google.cloud.firestore.v1.stub.FirestoreStub; import com.google.cloud.firestore.v1.stub.FirestoreStubSettings; import com.google.firestore.v1.BatchGetDocumentsRequest; import com.google.firestore.v1.BatchGetDocumentsResponse; @@ -40,8 +54,11 @@ import com.google.firestore.v1.CommitResponse; import com.google.firestore.v1.ExecutePipelineRequest; import com.google.firestore.v1.ExecutePipelineResponse; +import com.google.firestore.v1.ListCollectionIdsRequest; import com.google.firestore.v1.ListDocumentsRequest; import com.google.firestore.v1.ListDocumentsResponse; +import com.google.firestore.v1.ListenRequest; +import com.google.firestore.v1.ListenResponse; import com.google.firestore.v1.PartitionQueryRequest; import com.google.firestore.v1.PartitionQueryResponse; import com.google.firestore.v1.RollbackRequest; @@ -49,6 +66,8 @@ import com.google.firestore.v1.RunAggregationQueryResponse; import com.google.firestore.v1.RunQueryRequest; import com.google.firestore.v1.RunQueryResponse; +import com.google.firestore.v1.TransactionOptions; +import com.google.protobuf.ByteString; import com.google.protobuf.Empty; import java.io.IOException; import java.lang.reflect.Field; @@ -287,6 +306,302 @@ public void listDocumentsPagedCallableFollowsServiceConfig() throws Exception { .containsExactlyElementsIn(expectedSettings.getRetryableCodes()); } + @Test + public void commitCallableRoutingHeader() { + FirestoreStub mockStub = mock(FirestoreStub.class); + RecordingUnaryCallable callable = new RecordingUnaryCallable<>(); + when(mockStub.commitCallable()).thenReturn(callable); + GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(mockStub); + + rpc.commitCallable() + .futureCall(CommitRequest.getDefaultInstance(), GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("false"); + + rpc.commitCallable() + .futureCall( + CommitRequest.newBuilder().setTransaction(ByteString.copyFromUtf8("tx1")).build(), + GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("true"); + } + + @Test + public void batchWriteCallableRoutingHeader() { + FirestoreStub mockStub = mock(FirestoreStub.class); + RecordingUnaryCallable callable = + new RecordingUnaryCallable<>(); + when(mockStub.batchWriteCallable()).thenReturn(callable); + GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(mockStub); + + rpc.batchWriteCallable() + .futureCall(BatchWriteRequest.getDefaultInstance(), GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("false"); + } + + @Test + public void batchGetDocumentsCallableRoutingHeader() { + FirestoreStub mockStub = mock(FirestoreStub.class); + RecordingServerStreamingCallable callable = + new RecordingServerStreamingCallable<>(); + when(mockStub.batchGetDocumentsCallable()).thenReturn(callable); + GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(mockStub); + + rpc.batchGetDocumentsCallable() + .call(BatchGetDocumentsRequest.getDefaultInstance(), null, GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("false"); + + rpc.batchGetDocumentsCallable() + .call( + BatchGetDocumentsRequest.newBuilder() + .setTransaction(ByteString.copyFromUtf8("tx1")) + .build(), + null, + GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("true"); + + rpc.batchGetDocumentsCallable() + .call( + BatchGetDocumentsRequest.newBuilder() + .setNewTransaction(TransactionOptions.getDefaultInstance()) + .build(), + null, + GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("true"); + } + + @Test + public void runQueryCallableRoutingHeader() { + FirestoreStub mockStub = mock(FirestoreStub.class); + RecordingServerStreamingCallable callable = + new RecordingServerStreamingCallable<>(); + when(mockStub.runQueryCallable()).thenReturn(callable); + GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(mockStub); + + rpc.runQueryCallable() + .call(RunQueryRequest.getDefaultInstance(), null, GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("false"); + + rpc.runQueryCallable() + .call( + RunQueryRequest.newBuilder().setTransaction(ByteString.copyFromUtf8("tx1")).build(), + null, + GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("true"); + + rpc.runQueryCallable() + .call( + RunQueryRequest.newBuilder() + .setNewTransaction(TransactionOptions.getDefaultInstance()) + .build(), + null, + GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("true"); + } + + @Test + public void executePipelineCallableRoutingHeader() { + FirestoreStub mockStub = mock(FirestoreStub.class); + RecordingServerStreamingCallable callable = + new RecordingServerStreamingCallable<>(); + when(mockStub.executePipelineCallable()).thenReturn(callable); + GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(mockStub); + + rpc.executePipelineCallable() + .call(ExecutePipelineRequest.getDefaultInstance(), null, GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("false"); + + rpc.executePipelineCallable() + .call( + ExecutePipelineRequest.newBuilder() + .setTransaction(ByteString.copyFromUtf8("tx1")) + .build(), + null, + GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("true"); + + rpc.executePipelineCallable() + .call( + ExecutePipelineRequest.newBuilder() + .setNewTransaction(TransactionOptions.getDefaultInstance()) + .build(), + null, + GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("true"); + } + + @Test + public void runAggregationQueryCallableRoutingHeader() { + FirestoreStub mockStub = mock(FirestoreStub.class); + RecordingServerStreamingCallable + callable = new RecordingServerStreamingCallable<>(); + when(mockStub.runAggregationQueryCallable()).thenReturn(callable); + GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(mockStub); + + rpc.runAggregationQueryCallable() + .call( + RunAggregationQueryRequest.getDefaultInstance(), null, GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("false"); + + rpc.runAggregationQueryCallable() + .call( + RunAggregationQueryRequest.newBuilder() + .setTransaction(ByteString.copyFromUtf8("tx1")) + .build(), + null, + GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("true"); + + rpc.runAggregationQueryCallable() + .call( + RunAggregationQueryRequest.newBuilder() + .setNewTransaction(TransactionOptions.getDefaultInstance()) + .build(), + null, + GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("true"); + } + + @Test + public void beginTransactionCallableRoutingHeader() { + FirestoreStub mockStub = mock(FirestoreStub.class); + RecordingUnaryCallable callable = + new RecordingUnaryCallable<>(); + when(mockStub.beginTransactionCallable()).thenReturn(callable); + GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(mockStub); + + rpc.beginTransactionCallable() + .futureCall(BeginTransactionRequest.getDefaultInstance(), GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("true"); + } + + @Test + public void rollbackCallableRoutingHeader() { + FirestoreStub mockStub = mock(FirestoreStub.class); + RecordingUnaryCallable callable = new RecordingUnaryCallable<>(); + when(mockStub.rollbackCallable()).thenReturn(callable); + GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(mockStub); + + rpc.rollbackCallable() + .futureCall(RollbackRequest.getDefaultInstance(), GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("true"); + } + + @Test + public void listCollectionIdsPagedCallableRoutingHeader() { + FirestoreStub mockStub = mock(FirestoreStub.class); + RecordingUnaryCallable callable = + new RecordingUnaryCallable<>(); + when(mockStub.listCollectionIdsPagedCallable()).thenReturn(callable); + GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(mockStub); + + rpc.listCollectionIdsPagedCallable() + .futureCall(ListCollectionIdsRequest.getDefaultInstance(), GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("false"); + } + + @Test + public void partitionQueryPagedCallableRoutingHeader() { + FirestoreStub mockStub = mock(FirestoreStub.class); + RecordingUnaryCallable callable = + new RecordingUnaryCallable<>(); + when(mockStub.partitionQueryPagedCallable()).thenReturn(callable); + GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(mockStub); + + rpc.partitionQueryPagedCallable() + .futureCall(PartitionQueryRequest.getDefaultInstance(), GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("false"); + } + + @Test + public void listDocumentsPagedCallableRoutingHeader() { + FirestoreStub mockStub = mock(FirestoreStub.class); + RecordingUnaryCallable callable = + new RecordingUnaryCallable<>(); + when(mockStub.listDocumentsPagedCallable()).thenReturn(callable); + GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(mockStub); + + rpc.listDocumentsPagedCallable() + .futureCall(ListDocumentsRequest.getDefaultInstance(), GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("false"); + + rpc.listDocumentsPagedCallable() + .futureCall( + ListDocumentsRequest.newBuilder() + .setTransaction(ByteString.copyFromUtf8("tx1")) + .build(), + GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("true"); + } + + @Test + public void listenCallableRoutingHeader() { + FirestoreStub mockStub = mock(FirestoreStub.class); + RecordingBidiStreamingCallable callable = + new RecordingBidiStreamingCallable<>(); + when(mockStub.listenCallable()).thenReturn(callable); + GrpcFirestoreRpc rpc = new GrpcFirestoreRpc(mockStub); + + rpc.listenCallable().internalCall(null, null, GrpcCallContext.createDefault()); + assertThat(callable.lastContext.getExtraHeaders().get("x-goog-is-transaction")) + .containsExactly("false"); + } + + private static class RecordingUnaryCallable + extends UnaryCallable { + ApiCallContext lastContext; + + @Override + public ApiFuture futureCall(RequestT request, ApiCallContext context) { + this.lastContext = context; + return ApiFutures.immediateFuture(null); + } + } + + private static class RecordingServerStreamingCallable + extends ServerStreamingCallable { + ApiCallContext lastContext; + + @Override + public void call( + RequestT request, ResponseObserver responseObserver, ApiCallContext context) { + this.lastContext = context; + } + } + + private static class RecordingBidiStreamingCallable + extends BidiStreamingCallable { + ApiCallContext lastContext; + + @Override + public ClientStream internalCall( + ResponseObserver responseObserver, + ClientStreamReadyObserver onReady, + ApiCallContext context) { + this.lastContext = context; + return null; + } + } + private static CallableRetryData getRetryData(Object callable) throws Exception { String aClassName = callable.getClass().getName(); switch (aClassName) { @@ -296,6 +611,9 @@ private static CallableRetryData getRetryData(Object callable) throws Exception case "com.google.api.gax.rpc.UnaryCallable$1": case "com.google.api.gax.rpc.ServerStreamingCallable$1": return getRetryData(getViaReflection(callable, "this$0")); + case "com.google.cloud.firestore.spi.v1.GrpcFirestoreRpc$1": + case "com.google.cloud.firestore.spi.v1.GrpcFirestoreRpc$2": + return getRetryData(getViaReflection(callable, "val$callable")); case "com.google.api.gax.rpc.RetryingCallable": return new CallableRetryData( getRetrySettings(getViaReflection(callable, "executor")), From b2ce40f64216b4edf27529436423e72421b7bac1 Mon Sep 17 00:00:00 2001 From: Nikhil Date: Sat, 17 Oct 2026 09:48:35 -0700 Subject: [PATCH 2/2] Apply suggestion from @gemini-code-assist[bot] Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../google/cloud/firestore/spi/v1/GrpcFirestoreRpcTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-firestore/google-cloud-firestore/src/test/java/com/google/cloud/firestore/spi/v1/GrpcFirestoreRpcTest.java b/java-firestore/google-cloud-firestore/src/test/java/com/google/cloud/firestore/spi/v1/GrpcFirestoreRpcTest.java index e3f8d28b6e65..a5c09f687b12 100644 --- a/java-firestore/google-cloud-firestore/src/test/java/com/google/cloud/firestore/spi/v1/GrpcFirestoreRpcTest.java +++ b/java-firestore/google-cloud-firestore/src/test/java/com/google/cloud/firestore/spi/v1/GrpcFirestoreRpcTest.java @@ -611,9 +611,9 @@ private static CallableRetryData getRetryData(Object callable) throws Exception case "com.google.api.gax.rpc.UnaryCallable$1": case "com.google.api.gax.rpc.ServerStreamingCallable$1": return getRetryData(getViaReflection(callable, "this$0")); - case "com.google.cloud.firestore.spi.v1.GrpcFirestoreRpc$1": - case "com.google.cloud.firestore.spi.v1.GrpcFirestoreRpc$2": - return getRetryData(getViaReflection(callable, "val$callable")); + case "com.google.cloud.firestore.spi.v1.GrpcFirestoreRpc$RoutingMetadataUnaryCallable": + case "com.google.cloud.firestore.spi.v1.GrpcFirestoreRpc$RoutingMetadataServerStreamingCallable": + return getRetryData(getViaReflection(callable, "callable")); case "com.google.api.gax.rpc.RetryingCallable": return new CallableRetryData( getRetrySettings(getViaReflection(callable, "executor")),