Skip to content

Commit 6bc9820

Browse files
fix: pass deadline through ExecuteQuery RetrySettings (#2355)
Change-Id: I47fbb6761205c8ab34ecfa490954c56cf01b5288
1 parent 0330d77 commit 6bc9820

File tree

2 files changed

+79
-2
lines changed

2 files changed

+79
-2
lines changed

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStub.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,11 +1357,21 @@ public Map<String, String> extract(ExecuteQueryRequest executeQueryRequest) {
13571357

13581358
ServerStreamingCallSettings<ExecuteQueryCallContext, SqlRow> retrySettings =
13591359
ServerStreamingCallSettings.<ExecuteQueryCallContext, SqlRow>newBuilder()
1360-
// TODO resumption strategy and retry settings
1360+
// TODO add resumption strategy and pass through retry settings unchanged
1361+
// we pass through retry settings to use the deadlines now but don't
1362+
// support retries
1363+
.setRetrySettings(
1364+
settings
1365+
.executeQuerySettings()
1366+
.getRetrySettings()
1367+
.toBuilder()
1368+
// override maxAttempts as a safeguard against changes from user
1369+
.setMaxAttempts(1)
1370+
.build())
13611371
.build();
13621372

13631373
// Adding RetryingCallable to the callable chain so that client side metrics can be
1364-
// measured correctly. Retries are currently disabled.
1374+
// measured correctly and deadlines are set. Retries are currently disabled.
13651375
ServerStreamingCallable<ExecuteQueryCallContext, SqlRow> retries =
13661376
withRetries(withBigtableTracer, retrySettings);
13671377

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/sql/ExecuteQueryCallableTest.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import static com.google.common.truth.Truth.assertThat;
2323
import static org.junit.Assert.assertThrows;
2424

25+
import com.google.api.gax.retrying.RetrySettings;
2526
import com.google.api.gax.rpc.UnavailableException;
2627
import com.google.bigtable.v2.BigtableGrpc;
2728
import com.google.bigtable.v2.ExecuteQueryRequest;
@@ -35,18 +36,23 @@
3536
import com.google.cloud.bigtable.data.v2.models.sql.Statement;
3637
import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStub;
3738
import com.google.cloud.bigtable.gaxx.testing.FakeStreamingApi.ServerStreamingStashCallable;
39+
import com.google.common.collect.Range;
40+
import io.grpc.Context;
41+
import io.grpc.Deadline;
3842
import io.grpc.Server;
3943
import io.grpc.Status;
4044
import io.grpc.StatusRuntimeException;
4145
import io.grpc.stub.StreamObserver;
4246
import java.io.IOException;
4347
import java.util.Collections;
4448
import java.util.Iterator;
49+
import java.util.concurrent.TimeUnit;
4550
import org.junit.After;
4651
import org.junit.Before;
4752
import org.junit.Test;
4853
import org.junit.runner.RunWith;
4954
import org.junit.runners.JUnit4;
55+
import org.threeten.bp.Duration;
5056

5157
@RunWith(JUnit4.class)
5258
public class ExecuteQueryCallableTest {
@@ -108,13 +114,74 @@ public void testExecuteQueryRequestsAreNotRetried() {
108114
assertThat(fakeService.attempts).isEqualTo(1);
109115
}
110116

117+
@Test
118+
public void testExecuteQueryRequestsIgnoreOverriddenMaxAttempts() throws IOException {
119+
BigtableDataSettings.Builder overrideSettings =
120+
BigtableDataSettings.newBuilderForEmulator(server.getPort())
121+
.setProjectId("fake-project")
122+
.setInstanceId("fake-instance");
123+
overrideSettings
124+
.stubSettings()
125+
.executeQuerySettings()
126+
.setRetrySettings(RetrySettings.newBuilder().setMaxAttempts(10).build());
127+
EnhancedBigtableStub overrideStub =
128+
EnhancedBigtableStub.create(overrideSettings.build().getStubSettings());
129+
SqlServerStream stream =
130+
overrideStub.executeQueryCallable().call(Statement.of("SELECT * FROM table"));
131+
132+
Iterator<SqlRow> iterator = stream.rows().iterator();
133+
134+
assertThrows(UnavailableException.class, iterator::next).getCause();
135+
assertThat(fakeService.attempts).isEqualTo(1);
136+
}
137+
138+
@Test
139+
public void testExecuteQueryRequestsSetDefaultDeadline() {
140+
SqlServerStream stream = stub.executeQueryCallable().call(Statement.of("SELECT * FROM table"));
141+
Iterator<SqlRow> iterator = stream.rows().iterator();
142+
// We don't care about this but are reusing the fake service that tests retries
143+
assertThrows(UnavailableException.class, iterator::next).getCause();
144+
// We have 30s default, we assume less than 1s has been burned when the fake service sets it
145+
assertThat(fakeService.deadlineMillisRemaining).isIn(Range.closed(29000L, 30100L));
146+
}
147+
148+
@Test
149+
public void testExecuteQueryRequestsRespectOverridenDeadline() throws IOException {
150+
BigtableDataSettings.Builder overrideSettings =
151+
BigtableDataSettings.newBuilderForEmulator(server.getPort())
152+
.setProjectId("fake-project")
153+
.setInstanceId("fake-instance");
154+
overrideSettings
155+
.stubSettings()
156+
.executeQuerySettings()
157+
.setRetrySettings(
158+
RetrySettings.newBuilder()
159+
.setInitialRpcTimeout(Duration.ofMinutes(5))
160+
.setMaxRpcTimeout(Duration.ofMinutes(5))
161+
.build());
162+
EnhancedBigtableStub overrideDeadline =
163+
EnhancedBigtableStub.create(overrideSettings.build().getStubSettings());
164+
SqlServerStream streamOverride =
165+
overrideDeadline.executeQueryCallable().call(Statement.of("SELECT * FROM table"));
166+
Iterator<SqlRow> overrideIterator = streamOverride.rows().iterator();
167+
// We don't care about this but are reusing the fake service that tests retries
168+
assertThrows(UnavailableException.class, overrideIterator::next).getCause();
169+
// We have 30s default, we assume less than 1s has been burned when the fake service sets it
170+
assertThat(fakeService.deadlineMillisRemaining).isIn(Range.closed(299000L, 300100L));
171+
}
172+
111173
private static class FakeService extends BigtableGrpc.BigtableImplBase {
112174

113175
private int attempts = 0;
176+
private long deadlineMillisRemaining;
114177

115178
@Override
116179
public void executeQuery(
117180
ExecuteQueryRequest request, StreamObserver<ExecuteQueryResponse> responseObserver) {
181+
Deadline deadline = Context.current().getDeadline();
182+
if (deadline != null) {
183+
deadlineMillisRemaining = deadline.timeRemaining(TimeUnit.MILLISECONDS);
184+
}
118185
attempts++;
119186
responseObserver.onNext(metadata(columnMetadata("test", stringType())));
120187
responseObserver.onError(new StatusRuntimeException(Status.UNAVAILABLE));

0 commit comments

Comments
 (0)