Skip to content
This repository was archived by the owner on Feb 24, 2026. It is now read-only.

Commit 0261af4

Browse files
authored
feat: Add max size check to StreamWriterV2 (#873)
* Add a new StreamWriterV2. Compared to existing StreamWriter, its locking mechanism is much simpler. * Stop using Java8 features as we still need to support Java7 * Do not hold lock while sending requests, and some minor refactoring. * Add max message size check.
1 parent de747ec commit 0261af4

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

google-cloud-bigquerystorage/src/main/java/com/google/cloud/bigquery/storage/v1beta2/StreamWriterV2.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.common.base.Preconditions;
2323
import com.google.common.util.concurrent.Uninterruptibles;
2424
import io.grpc.Status;
25+
import io.grpc.Status.Code;
2526
import io.grpc.StatusRuntimeException;
2627
import java.util.Deque;
2728
import java.util.LinkedList;
@@ -39,8 +40,6 @@
3940
*
4041
* <p>TODO: Attach schema.
4142
*
42-
* <p>TODO: Add max size check.
43-
*
4443
* <p>TODO: Add inflight control.
4544
*
4645
* <p>TODO: Attach traceId.
@@ -94,6 +93,11 @@ public class StreamWriterV2 implements AutoCloseable {
9493
*/
9594
private Thread appendThread;
9695

96+
/** The maximum size of one request. Defined by the API. */
97+
public static long getApiMaxRequestBytes() {
98+
return 8L * 1000L * 1000L; // 8 megabytes (https://en.wikipedia.org/wiki/Megabyte)
99+
}
100+
97101
private StreamWriterV2(Builder builder) {
98102
this.lock = new ReentrantLock();
99103
this.hasMessageInWaitingQueue = lock.newCondition();
@@ -154,6 +158,17 @@ public void run() {
154158
*/
155159
public ApiFuture<AppendRowsResponse> append(AppendRowsRequest message) {
156160
AppendRequestAndResponse requestWrapper = new AppendRequestAndResponse(message);
161+
if (requestWrapper.messageSize > getApiMaxRequestBytes()) {
162+
requestWrapper.appendResult.setException(
163+
new StatusRuntimeException(
164+
Status.fromCode(Code.INVALID_ARGUMENT)
165+
.withDescription(
166+
"MessageSize is too large. Max allow: "
167+
+ getApiMaxRequestBytes()
168+
+ " Actual: "
169+
+ requestWrapper.messageSize)));
170+
return requestWrapper.appendResult;
171+
}
157172
this.lock.lock();
158173
try {
159174
if (userClosed) {
@@ -355,10 +370,12 @@ public StreamWriterV2 build() {
355370
private static final class AppendRequestAndResponse {
356371
final SettableApiFuture<AppendRowsResponse> appendResult;
357372
final AppendRowsRequest message;
373+
final long messageSize;
358374

359375
AppendRequestAndResponse(AppendRowsRequest message) {
360376
this.appendResult = SettableApiFuture.create();
361377
this.message = message;
378+
this.messageSize = message.getProtoRows().getSerializedSize();
362379
}
363380
}
364381
}

google-cloud-bigquerystorage/src/test/java/com/google/cloud/bigquery/storage/v1beta2/StreamWriterV2Test.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.google.api.gax.rpc.ApiException;
2727
import com.google.api.gax.rpc.StatusCode.Code;
2828
import com.google.cloud.bigquery.storage.test.Test.FooType;
29+
import com.google.common.base.Strings;
2930
import com.google.protobuf.DescriptorProtos;
3031
import com.google.protobuf.Int64Value;
3132
import io.grpc.Status;
@@ -288,6 +289,20 @@ public void serverCloseWhileRequestsInflight() throws Exception {
288289
}
289290

290291
writer.close();
291-
;
292+
}
293+
294+
@Test
295+
public void testMessageTooLarge() {
296+
StreamWriterV2 writer = getTestStreamWriterV2();
297+
298+
String oversized = Strings.repeat("a", (int) (StreamWriterV2.getApiMaxRequestBytes() + 1));
299+
ApiFuture<AppendRowsResponse> appendFuture1 = sendTestMessage(writer, new String[] {oversized});
300+
assertTrue(appendFuture1.isDone());
301+
StatusRuntimeException actualError =
302+
assertFutureException(StatusRuntimeException.class, appendFuture1);
303+
assertEquals(Status.Code.INVALID_ARGUMENT, actualError.getStatus().getCode());
304+
assertTrue(actualError.getStatus().getDescription().contains("MessageSize is too large"));
305+
306+
writer.close();
292307
}
293308
}

0 commit comments

Comments
 (0)