Skip to content

Commit 9d421c1

Browse files
committed
feat(gax): add ResumableUploadFutureImpl state machine and ResumableUploadClient SPI
- Add ResumableUploadFutureImpl stateful per-request state machine. - Add ResumableUploadClient transport SPI interface and value objects (ResumableUploadSession, ChunkUploadRequest, ChunkUploadResponse). - Update ResumableUploadCallable to instantiate and start ResumableUploadFutureImpl.
1 parent 04f55d0 commit 9d421c1

5 files changed

Lines changed: 453 additions & 0 deletions

File tree

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are
6+
* met:
7+
*
8+
* * Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above
11+
* copyright notice, this list of conditions and the following disclaimer
12+
* in the documentation and/or other materials provided with the
13+
* distribution.
14+
* * Neither the name of Google LLC nor the names of its
15+
* contributors may be used to endorse or promote products derived from
16+
* this software without specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
package com.google.api.gax.rpc;
31+
32+
import com.google.api.core.BetaApi;
33+
import com.google.common.base.Preconditions;
34+
35+
/** Value object representing a chunk upload request. */
36+
@BetaApi
37+
public class ChunkUploadRequest {
38+
39+
private final String uploadUrl;
40+
private final byte[] data;
41+
private final long offset;
42+
private final long totalSize;
43+
private final boolean isLast;
44+
45+
public ChunkUploadRequest(
46+
String uploadUrl, byte[] data, long offset, long totalSize, boolean isLast) {
47+
this.uploadUrl = Preconditions.checkNotNull(uploadUrl);
48+
this.data = Preconditions.checkNotNull(data);
49+
this.offset = offset;
50+
this.totalSize = totalSize;
51+
this.isLast = isLast;
52+
}
53+
54+
public String getUploadUrl() {
55+
return uploadUrl;
56+
}
57+
58+
public byte[] getData() {
59+
return data;
60+
}
61+
62+
public long getOffset() {
63+
return offset;
64+
}
65+
66+
public long getTotalSize() {
67+
return totalSize;
68+
}
69+
70+
public boolean isLast() {
71+
return isLast;
72+
}
73+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are
6+
* met:
7+
*
8+
* * Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above
11+
* copyright notice, this list of conditions and the following disclaimer
12+
* in the documentation and/or other materials provided with the
13+
* distribution.
14+
* * Neither the name of Google LLC nor the names of its
15+
* contributors may be used to endorse or promote products derived from
16+
* this software without specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
package com.google.api.gax.rpc;
31+
32+
import com.google.api.core.BetaApi;
33+
import javax.annotation.Nullable;
34+
35+
/** Value object representing a chunk upload response. */
36+
@BetaApi
37+
public class ChunkUploadResponse {
38+
39+
private final long committedOffset;
40+
@Nullable private final Object responseBody;
41+
42+
public ChunkUploadResponse(long committedOffset, @Nullable Object responseBody) {
43+
this.committedOffset = committedOffset;
44+
this.responseBody = responseBody;
45+
}
46+
47+
public long getCommittedOffset() {
48+
return committedOffset;
49+
}
50+
51+
@Nullable
52+
public Object getResponseBody() {
53+
return responseBody;
54+
}
55+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are
6+
* met:
7+
*
8+
* * Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above
11+
* copyright notice, this list of conditions and the following disclaimer
12+
* in the documentation and/or other materials provided with the
13+
* distribution.
14+
* * Neither the name of Google LLC nor the names of its
15+
* contributors may be used to endorse or promote products derived from
16+
* this software without specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
package com.google.api.gax.rpc;
31+
32+
import com.google.api.core.BetaApi;
33+
34+
/**
35+
* Low-level transport Service Provider Interface (SPI) for executing individual Scotty resumable
36+
* upload operations (session initiation, chunk upload, and status querying).
37+
*/
38+
@BetaApi
39+
public interface ResumableUploadClient {
40+
41+
/** Returns a UnaryCallable to initiate a new resumable upload session. */
42+
<RequestT> UnaryCallable<RequestT, ResumableUploadSession> startUploadCallable();
43+
44+
/** Returns a UnaryCallable to upload a payload byte chunk to an active session URL. */
45+
UnaryCallable<ChunkUploadRequest, ChunkUploadResponse> uploadChunkCallable();
46+
47+
/** Returns a UnaryCallable to query the server's committed byte offset for a session URL. */
48+
UnaryCallable<String, Long> queryStatusCallable();
49+
}

0 commit comments

Comments
 (0)