Skip to content

Commit bf49cf9

Browse files
fix: handling of totalTimeout on sql plan refresh (#2541)
Change-Id: I76d99d11c014b5602c28495c6f82b515542860e0 Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/java-bigtable/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) - [ ] Rollback plan is reviewed and LGTMed - [ ] All new data plane features have a completed end to end testing plan Fixes #<issue_number_goes_here> ☕️ If you write sample code, please follow the [samples format]( https://togithub.com/GoogleCloudPlatform/java-docs-samples/blob/main/SAMPLE_FORMAT.md).
1 parent 77213a6 commit bf49cf9

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import com.google.cloud.bigtable.data.v2.models.sql.PreparedStatementRefreshTimeoutException;
3232
import com.google.cloud.bigtable.data.v2.models.sql.ResultSetMetadata;
3333
import com.google.cloud.bigtable.data.v2.stub.SafeResponseObserver;
34+
import com.google.common.annotations.VisibleForTesting;
3435
import com.google.rpc.PreconditionFailure;
3536
import com.google.rpc.PreconditionFailure.Violation;
3637
import io.grpc.Deadline;
@@ -104,7 +105,8 @@ public void call(
104105

105106
// Checks for an attempt timeout first, then a total timeout. If found, converts the timeout
106107
// to an absolute deadline. Adjusts totalTimeout based on the time since startTimeOfOverallRequest
107-
private static @Nullable Deadline getDeadline(
108+
@VisibleForTesting
109+
static @Nullable Deadline getDeadline(
108110
GrpcCallContext grpcCallContext, Instant startTimeOfOverallRequest) {
109111
Optional<Deadline> attemptDeadline =
110112
Optional.ofNullable(grpcCallContext)
@@ -123,7 +125,7 @@ public void call(
123125
Duration elapsedTime = Duration.between(startTimeOfOverallRequest, Instant.now());
124126
Duration remaining = d.minus(elapsedTime);
125127
// zero is treated as no deadline, so if full deadline is elapsed pass 1 nano
126-
long adjusted = Math.max(remaining.getNano(), 1);
128+
long adjusted = Math.max(remaining.toNanos(), 1);
127129
return Deadline.after(adjusted, TimeUnit.NANOSECONDS);
128130
})
129131
.orElse(null);

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

+44
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import io.grpc.Deadline;
6161
import io.grpc.Status.Code;
6262
import java.time.Duration;
63+
import java.time.Instant;
6364
import java.util.Collections;
6465
import java.util.concurrent.ExecutionException;
6566
import java.util.concurrent.Executors;
@@ -282,4 +283,47 @@ public void planRefreshDelayIsFactoredIntoExecuteTimeout() throws InterruptedExc
282283
Deadline executeDeadline = grpcCallContext.getCallOptions().getDeadline();
283284
assertThat(executeDeadline.isBefore(paddedDeadlineAtStartOfCall)).isTrue();
284285
}
286+
287+
@Test
288+
public void testGetDeadlineWithAttemptTimeout() {
289+
GrpcCallContext callContext =
290+
GrpcCallContext.createDefault().withTimeoutDuration(Duration.ofMinutes(1));
291+
// startTimeOfOverallRequest doesn't matter here
292+
Deadline deadline = PlanRefreshingCallable.getDeadline(callContext, Instant.now());
293+
long millisRemaining = deadline.timeRemaining(TimeUnit.MILLISECONDS);
294+
assertThat(millisRemaining).isLessThan((60 * 1000) + 1);
295+
// Give some padding in case tests are very slow
296+
assertThat(millisRemaining).isGreaterThan(58 * 1000);
297+
}
298+
299+
@Test
300+
public void testGetDeadlineWithTotalTimeout() {
301+
GrpcCallContext callContext =
302+
GrpcCallContext.createDefault()
303+
.withRetrySettings(
304+
RetrySettings.newBuilder()
305+
.setTotalTimeout(org.threeten.bp.Duration.ofMinutes(1))
306+
.build());
307+
Deadline deadline = PlanRefreshingCallable.getDeadline(callContext, Instant.now());
308+
long millisRemaining = deadline.timeRemaining(TimeUnit.MILLISECONDS);
309+
assertThat(millisRemaining).isLessThan((60 * 1000) + 1);
310+
// Give some padding in case tests are very slow
311+
assertThat(millisRemaining).isGreaterThan(58 * 1000);
312+
}
313+
314+
@Test
315+
public void testAttemptTimeoutUsedOverTotalTimeout() {
316+
GrpcCallContext callContext =
317+
GrpcCallContext.createDefault()
318+
.withTimeoutDuration(Duration.ofMinutes(1))
319+
.withRetrySettings(
320+
RetrySettings.newBuilder()
321+
.setTotalTimeout(org.threeten.bp.Duration.ofHours(1))
322+
.build());
323+
Deadline deadline = PlanRefreshingCallable.getDeadline(callContext, Instant.now());
324+
long millisRemaining = deadline.timeRemaining(TimeUnit.MILLISECONDS);
325+
assertThat(millisRemaining).isLessThan((60 * 1000) + 1);
326+
// Give some padding in case tests are very slow
327+
assertThat(millisRemaining).isGreaterThan(58 * 1000);
328+
}
285329
}

0 commit comments

Comments
 (0)