From 2cf552117d9ae301eae55568f7dbce322f913b3d Mon Sep 17 00:00:00 2001 From: Blake Li Date: Wed, 12 Aug 2026 05:54:55 +0000 Subject: [PATCH] feat(gax): add ResumableUploadCallable and ResumableUploadCallSettings Clean up ResumableUploadCallSettingsTest JUnit 5 test suite by removing redundant equals/hashCode test for @AutoValue. Add ResumableUploadCallable abstract base class. --- .../gax/rpc/ResumableUploadCallSettings.java | 77 +++++++++++++++++++ .../api/gax/rpc/ResumableUploadCallable.java | 60 +++++++++++++++ .../rpc/ResumableUploadCallSettingsTest.java | 77 +++++++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResumableUploadCallSettings.java create mode 100644 sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResumableUploadCallable.java create mode 100644 sdk-platform-java/gax-java/gax/src/test/java/com/google/api/gax/rpc/ResumableUploadCallSettingsTest.java diff --git a/sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResumableUploadCallSettings.java b/sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResumableUploadCallSettings.java new file mode 100644 index 000000000000..aab8918ac604 --- /dev/null +++ b/sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResumableUploadCallSettings.java @@ -0,0 +1,77 @@ +/* + * Copyright 2026 Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.google.api.gax.rpc; + +import com.google.api.core.BetaApi; +import com.google.auto.value.AutoValue; + +/** + * A settings class to configure a {@link ResumableUploadCallable} for executing resumable + * uploads. Encapsulates protocol options such as payload chunk size. + */ +@BetaApi +@AutoValue +public abstract class ResumableUploadCallSettings { + private static final int DEFAULT_CHUNK_SIZE = 8 * 1024 * 1024; // 8 MB + + /** Returns the configured chunk size in bytes (defaults to 8 MB / 8,388,608 bytes). */ + public abstract int getChunkSize(); + + /** + * Merges another {@code ResumableUploadCallSettings} instance with this one. + * Fields set in {@code other} override fields in this instance. + * + * @param other settings to overlay; may be {@code null} + * @return a new, resolved {@code ResumableUploadCallSettings} instance + */ + public ResumableUploadCallSettings merge(ResumableUploadCallSettings other) { + if (other == null) { + return this; + } + return toBuilder().setChunkSize(other.getChunkSize()).build(); + } + + public abstract Builder toBuilder(); + + public static Builder newBuilder() { + return new AutoValue_ResumableUploadCallSettings.Builder() + .setChunkSize(DEFAULT_CHUNK_SIZE); + } + + /** Builder for {@link ResumableUploadCallSettings}. */ + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder setChunkSize(int chunkSize); + + public abstract int getChunkSize(); + + public abstract ResumableUploadCallSettings build(); + } +} diff --git a/sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResumableUploadCallable.java b/sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResumableUploadCallable.java new file mode 100644 index 000000000000..8b68f1eb94cf --- /dev/null +++ b/sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResumableUploadCallable.java @@ -0,0 +1,60 @@ +/* + * Copyright 2026 Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.google.api.gax.rpc; + +import com.google.api.core.ApiFuture; +import com.google.api.core.BetaApi; +import java.io.InputStream; + +/** + * A ResumableUploadCallable is an API-transport-independent wrapper for the Resumable Upload + * protocol. Operates directly on the request object and input stream payload. + * + * @param request type + * @param response type + */ +@BetaApi +public abstract class ResumableUploadCallable { + + protected ResumableUploadCallable() {} + + /** + * Performs the resumable upload asynchronously with custom call settings. + * + * @param request the request message + * @param payload the data payload input stream + * @param settings call settings overrides; may be {@code null} + * @return future for the response + */ + public abstract ApiFuture futureCall( + RequestT request, + InputStream payload, + ResumableUploadCallSettings settings); +} diff --git a/sdk-platform-java/gax-java/gax/src/test/java/com/google/api/gax/rpc/ResumableUploadCallSettingsTest.java b/sdk-platform-java/gax-java/gax/src/test/java/com/google/api/gax/rpc/ResumableUploadCallSettingsTest.java new file mode 100644 index 000000000000..d890c61e4ba0 --- /dev/null +++ b/sdk-platform-java/gax-java/gax/src/test/java/com/google/api/gax/rpc/ResumableUploadCallSettingsTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2026 Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.google.api.gax.rpc; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; + +import org.junit.jupiter.api.Test; + +public class ResumableUploadCallSettingsTest { + + @Test + public void testDefaultChunkSizeInBuilder() { + ResumableUploadCallSettings settings = ResumableUploadCallSettings.newBuilder().build(); + + assertEquals(8 * 1024 * 1024, settings.getChunkSize()); + } + + @Test + public void testCustomInitialization() { + ResumableUploadCallSettings settings = + ResumableUploadCallSettings.newBuilder().setChunkSize(16 * 1024 * 1024).build(); + + assertEquals(16 * 1024 * 1024, settings.getChunkSize()); + } + + @Test + public void testMerge_NullSettings() { + ResumableUploadCallSettings stubSettings = + ResumableUploadCallSettings.newBuilder().setChunkSize(4 * 1024 * 1024).build(); + + ResumableUploadCallSettings merged = stubSettings.merge(null); + + assertSame(stubSettings, merged); + } + + @Test + public void testMerge_SettingsOverrides() { + ResumableUploadCallSettings stubSettings = + ResumableUploadCallSettings.newBuilder().setChunkSize(4 * 1024 * 1024).build(); + + ResumableUploadCallSettings perRequestSettings = + ResumableUploadCallSettings.newBuilder().setChunkSize(32 * 1024 * 1024).build(); + + ResumableUploadCallSettings merged = stubSettings.merge(perRequestSettings); + + // Chunk size overridden by Tier-1 per-request settings + assertEquals(32 * 1024 * 1024, merged.getChunkSize()); + } +}