From f21e2924f3fa8983095e6bd5fc9f2f5581217a8f Mon Sep 17 00:00:00 2001 From: Liam Huffman Date: Wed, 3 Sep 2025 12:12:14 -0700 Subject: [PATCH 1/6] feat(bigquery): implement custom retry algo samples --- .../bigquery/SetCustomRetryAlgorithm.java | 67 +++++++++++++++++++ .../bigquery/SetCustomRetryAlgorithmIT.java | 64 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 samples/snippets/src/main/java/com/example/bigquery/SetCustomRetryAlgorithm.java create mode 100644 samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java diff --git a/samples/snippets/src/main/java/com/example/bigquery/SetCustomRetryAlgorithm.java b/samples/snippets/src/main/java/com/example/bigquery/SetCustomRetryAlgorithm.java new file mode 100644 index 0000000000..5fe32d70f3 --- /dev/null +++ b/samples/snippets/src/main/java/com/example/bigquery/SetCustomRetryAlgorithm.java @@ -0,0 +1,67 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.bigquery; + +// [START bigquery_set_custom_retry_algorithm] +import com.google.api.gax.retrying.ResultRetryAlgorithm; +import com.google.cloud.ExceptionHandler; +import com.google.cloud.bigquery.BigQuery; +import com.google.cloud.bigquery.BigQueryOptions; +import java.util.concurrent.TimeoutException; + +public class SetCustomRetryAlgorithm { + // In order to use a custom retry algorithm, you must implement a custom + // Interceptor that implements the ExceptionHandler.Interceptor interface. + public static final ExceptionHandler.Interceptor EXCEPTION_HANDLER_INTERCEPTOR = + new ExceptionHandler.Interceptor() { + public ExceptionHandler.Interceptor.RetryResult afterEval( + Exception exception, ExceptionHandler.Interceptor.RetryResult retryResult) { + return RetryResult.CONTINUE_EVALUATION; + } + + public ExceptionHandler.Interceptor.RetryResult beforeEval(Exception exception) { + return RetryResult.CONTINUE_EVALUATION; + } + }; + + public static void main(String... args) { + // TODO(developer): Replace projectId and exception classes before running + // the sample. + String projectId = "project-id"; + ResultRetryAlgorithm retryAlgorithm = + ExceptionHandler.newBuilder() + .abortOn(RuntimeException.class) + .retryOn(TimeoutException.class) + .addInterceptors(EXCEPTION_HANDLER_INTERCEPTOR) + .build(); + setCustomRetryAlgorithm(projectId, retryAlgorithm); + } + + public static void setCustomRetryAlgorithm( + String projectId, ResultRetryAlgorithm retryAlgorithm) { + BigQueryOptions options = + BigQueryOptions.newBuilder() + .setProjectId(projectId) + .setResultRetryAlgorithm(retryAlgorithm) + .build(); + + BigQuery bigquery = options.getService(); + + System.out.println(bigquery.getOptions().getResultRetryAlgorithm()); + } +} +// [END bigquery_set_custom_retry_algorithm] diff --git a/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java b/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java new file mode 100644 index 0000000000..637e729781 --- /dev/null +++ b/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java @@ -0,0 +1,64 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.bigquery; + +import static com.google.common.truth.Truth.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class SetCustomRetryAlgorithmTest { + private final Logger log = Logger.getLogger(this.getClass().getName()); + private ByteArrayOutputStream bout; + private PrintStream out; + private PrintStream originalPrintStream; + + private static final String PROJECT_ID = requireEnvVar("GOOGLE_CLOUD_PROJECT"); + + @Before + public void setUp() throws Exception { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + originalPrintStream = System.out; + System.setOut(out); + } + + @After + public void tearDown() { + System.out.flush(); + System.setOut(originalPrintStream); + log.log(Level.INFO, "\n" + bout.toString()); + } + + @Test + public void testSetCustomRetryAlgorithm() { + ResultRetryAlgorithm retryAlgorithm = + ExceptionHandler.newBuilder() + .abortOn(RuntimeException.class) + .retryOn(TimeoutException.class) + .addInterceptors(SetCustomRetryAlgorithm.EXCEPTION_HANDLER_INTERCEPTOR) + .build(); + + SetCustomRetryAlgorithm.setCustomRetryAlgorithm(PROJECT_ID, retryAlgorithm); + assertThat(bout.toString().contains("r")); + } +} From 7cae8c7b99009b91f2f5c8d92ad1cdfce61cacea Mon Sep 17 00:00:00 2001 From: Liam Huffman Date: Wed, 3 Sep 2025 12:15:49 -0700 Subject: [PATCH 2/6] change test to IT in file and class names --- .../java/com/example/bigquery/SetCustomRetryAlgorithmIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java b/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java index 637e729781..b557f6debf 100644 --- a/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java +++ b/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java @@ -26,7 +26,7 @@ import org.junit.Before; import org.junit.Test; -public class SetCustomRetryAlgorithmTest { +public class SetCustomRetryAlgorithmIT { private final Logger log = Logger.getLogger(this.getClass().getName()); private ByteArrayOutputStream bout; private PrintStream out; From 9a4218adb7e5661a2b1528a1f94cf952dd9390d4 Mon Sep 17 00:00:00 2001 From: Liam Huffman Date: Wed, 3 Sep 2025 12:28:59 -0700 Subject: [PATCH 3/6] add imports --- .../example/bigquery/SetCustomRetryAlgorithmIT.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java b/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java index b557f6debf..e2f2d35890 100644 --- a/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java +++ b/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java @@ -18,8 +18,11 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.api.gax.retrying.ResultRetryAlgorithm; +import com.google.cloud.ExceptionHandler; import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.util.concurrent.TimeoutException; import java.util.logging.Level; import java.util.logging.Logger; import org.junit.After; @@ -34,6 +37,14 @@ public class SetCustomRetryAlgorithmIT { private static final String PROJECT_ID = requireEnvVar("GOOGLE_CLOUD_PROJECT"); + private static String requireEnvVar(String varName) { + String value = System.getenv(varName); + assertNotNull( + "Environment variable " + varName + " is required to perform these tests.", + System.getenv(varName)); + return value; + } + @Before public void setUp() throws Exception { bout = new ByteArrayOutputStream(); @@ -59,6 +70,6 @@ public void testSetCustomRetryAlgorithm() { .build(); SetCustomRetryAlgorithm.setCustomRetryAlgorithm(PROJECT_ID, retryAlgorithm); - assertThat(bout.toString().contains("r")); + assertThat(bout.toString().contains("com.google.cloud.ExceptionHandler")); } } From 317dc35e4f1d52a575f1dc7649e92c27257bd9f6 Mon Sep 17 00:00:00 2001 From: Liam Huffman Date: Wed, 3 Sep 2025 12:34:04 -0700 Subject: [PATCH 4/6] add assertNotNull import --- .../java/com/example/bigquery/SetCustomRetryAlgorithmIT.java | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java b/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java index e2f2d35890..12ec7d429c 100644 --- a/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java +++ b/samples/snippets/src/test/java/com/example/bigquery/SetCustomRetryAlgorithmIT.java @@ -17,6 +17,7 @@ package com.example.bigquery; import static com.google.common.truth.Truth.assertThat; +import static junit.framework.TestCase.assertNotNull; import com.google.api.gax.retrying.ResultRetryAlgorithm; import com.google.cloud.ExceptionHandler; From 321026fcb93beb5be9c8ebaa8733023e35f4ba31 Mon Sep 17 00:00:00 2001 From: Liam Huffman Date: Thu, 4 Sep 2025 10:19:40 -0700 Subject: [PATCH 5/6] replace custom interceptor with BaseService interceptor --- .../bigquery/SetCustomRetryAlgorithm.java | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/samples/snippets/src/main/java/com/example/bigquery/SetCustomRetryAlgorithm.java b/samples/snippets/src/main/java/com/example/bigquery/SetCustomRetryAlgorithm.java index 5fe32d70f3..14595426e5 100644 --- a/samples/snippets/src/main/java/com/example/bigquery/SetCustomRetryAlgorithm.java +++ b/samples/snippets/src/main/java/com/example/bigquery/SetCustomRetryAlgorithm.java @@ -18,35 +18,29 @@ // [START bigquery_set_custom_retry_algorithm] import com.google.api.gax.retrying.ResultRetryAlgorithm; +import com.google.cloud.BaseService; import com.google.cloud.ExceptionHandler; import com.google.cloud.bigquery.BigQuery; import com.google.cloud.bigquery.BigQueryOptions; -import java.util.concurrent.TimeoutException; public class SetCustomRetryAlgorithm { - // In order to use a custom retry algorithm, you must implement a custom - // Interceptor that implements the ExceptionHandler.Interceptor interface. - public static final ExceptionHandler.Interceptor EXCEPTION_HANDLER_INTERCEPTOR = - new ExceptionHandler.Interceptor() { - public ExceptionHandler.Interceptor.RetryResult afterEval( - Exception exception, ExceptionHandler.Interceptor.RetryResult retryResult) { - return RetryResult.CONTINUE_EVALUATION; - } - - public ExceptionHandler.Interceptor.RetryResult beforeEval(Exception exception) { - return RetryResult.CONTINUE_EVALUATION; - } - }; - public static void main(String... args) { - // TODO(developer): Replace projectId and exception classes before running - // the sample. + // TODO(developer): Replace projectId and retryAlgorithm classes before + // running the sample. The ResultRetryAlgorithm abortOn and retryOn methods + // can be used to specify retry behavior when the client encounters + // exceptions during its execution. String projectId = "project-id"; ResultRetryAlgorithm retryAlgorithm = ExceptionHandler.newBuilder() .abortOn(RuntimeException.class) - .retryOn(TimeoutException.class) - .addInterceptors(EXCEPTION_HANDLER_INTERCEPTOR) + .retryOn(java.net.ConnectException.class) + .retryOn(java.net.UnknownHostException.class) + .retryOn(java.net.SocketException.class) + // Alternatively, you can create your own Interceptor object that + // implements the com.google.cloud.ExceptionHandler.Interceptor + // interface. See + // https://github.com/googleapis/sdk-platform-java/blob/f18318660c05d0d8466e3ead7127f0747fac2e2e/java-core/google-cloud-core/src/main/java/com/google/cloud/ExceptionHandler.java#L49 + .addInterceptors(BaseService.EXCEPTION_HANDLER_INTERCEPTOR) .build(); setCustomRetryAlgorithm(projectId, retryAlgorithm); } From c4659535fe9ed779c20b9d2331c68319b339b3d8 Mon Sep 17 00:00:00 2001 From: Liam Huffman Date: Thu, 4 Sep 2025 11:34:37 -0700 Subject: [PATCH 6/6] consolidate todo comments into one place --- .../java/com/example/bigquery/SetCustomRetryAlgorithm.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/samples/snippets/src/main/java/com/example/bigquery/SetCustomRetryAlgorithm.java b/samples/snippets/src/main/java/com/example/bigquery/SetCustomRetryAlgorithm.java index 14595426e5..df19e93c96 100644 --- a/samples/snippets/src/main/java/com/example/bigquery/SetCustomRetryAlgorithm.java +++ b/samples/snippets/src/main/java/com/example/bigquery/SetCustomRetryAlgorithm.java @@ -28,7 +28,8 @@ public static void main(String... args) { // TODO(developer): Replace projectId and retryAlgorithm classes before // running the sample. The ResultRetryAlgorithm abortOn and retryOn methods // can be used to specify retry behavior when the client encounters - // exceptions during its execution. + // exceptions during its execution. Alternatively, you can create your own + // custom class that implements the ResultRetryAlgorithm interface. String projectId = "project-id"; ResultRetryAlgorithm retryAlgorithm = ExceptionHandler.newBuilder() @@ -36,10 +37,6 @@ public static void main(String... args) { .retryOn(java.net.ConnectException.class) .retryOn(java.net.UnknownHostException.class) .retryOn(java.net.SocketException.class) - // Alternatively, you can create your own Interceptor object that - // implements the com.google.cloud.ExceptionHandler.Interceptor - // interface. See - // https://github.com/googleapis/sdk-platform-java/blob/f18318660c05d0d8466e3ead7127f0747fac2e2e/java-core/google-cloud-core/src/main/java/com/google/cloud/ExceptionHandler.java#L49 .addInterceptors(BaseService.EXCEPTION_HANDLER_INTERCEPTOR) .build(); setCustomRetryAlgorithm(projectId, retryAlgorithm);