Skip to content

Commit 05fe6d2

Browse files
authored
Expose subscribeTimeout config for BlockingOutputStreamAsyncRequestBody (#5000)
1 parent 6aac375 commit 05fe6d2

File tree

4 files changed

+64
-10
lines changed

4 files changed

+64
-10
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "",
5+
"description": "Allow users to configure `subscribeTimeout` for BlockingOutputStreamAsyncRequestBody. See [#4893](https://github.com/aws/aws-sdk-java-v2/issues/4893)"
6+
}

core/sdk-core/src/main/java/software/amazon/awssdk/core/async/AsyncRequestBody.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ static BlockingInputStreamAsyncRequestBody forBlockingInputStream(Long contentLe
418418
* <p>The caller is responsible for calling {@link OutputStream#close()} on the
419419
* {@link BlockingOutputStreamAsyncRequestBody#outputStream()} when writing is complete.
420420
*
421+
* <p>By default, it will time out if streaming hasn't started within 10 seconds, and you can configure the timeout
422+
* via {@link BlockingOutputStreamAsyncRequestBody#builder()}
421423
* <p><b>Example Usage</b>
422424
* <p>
423425
* {@snippet :
@@ -440,9 +442,12 @@ static BlockingInputStreamAsyncRequestBody forBlockingInputStream(Long contentLe
440442
* // Wait for the service to respond.
441443
* PutObjectResponse response = responseFuture.join();
442444
* }
445+
* @see BlockingOutputStreamAsyncRequestBody
443446
*/
444447
static BlockingOutputStreamAsyncRequestBody forBlockingOutputStream(Long contentLength) {
445-
return new BlockingOutputStreamAsyncRequestBody(contentLength);
448+
return BlockingOutputStreamAsyncRequestBody.builder()
449+
.contentLength(contentLength)
450+
.build();
446451
}
447452

448453
/**

core/sdk-core/src/main/java/software/amazon/awssdk/core/async/BlockingOutputStreamAsyncRequestBody.java

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import software.amazon.awssdk.core.exception.NonRetryableException;
2828
import software.amazon.awssdk.core.internal.util.NoopSubscription;
2929
import software.amazon.awssdk.utils.CancellableOutputStream;
30+
import software.amazon.awssdk.utils.Validate;
3031
import software.amazon.awssdk.utils.async.OutputStreamPublisher;
3132

3233
/**
@@ -46,13 +47,11 @@ public final class BlockingOutputStreamAsyncRequestBody implements AsyncRequestB
4647
private final Long contentLength;
4748
private final Duration subscribeTimeout;
4849

49-
BlockingOutputStreamAsyncRequestBody(Long contentLength) {
50-
this(contentLength, Duration.ofSeconds(10));
51-
}
52-
53-
BlockingOutputStreamAsyncRequestBody(Long contentLength, Duration subscribeTimeout) {
54-
this.contentLength = contentLength;
55-
this.subscribeTimeout = subscribeTimeout;
50+
private BlockingOutputStreamAsyncRequestBody(Builder builder) {
51+
this.contentLength = builder.contentLength;
52+
this.subscribeTimeout = Validate.isPositiveOrNull(builder.subscribeTimeout, "subscribeTimeout") != null ?
53+
builder.subscribeTimeout :
54+
Duration.ofSeconds(10);
5655
}
5756

5857
/**
@@ -69,6 +68,13 @@ public CancellableOutputStream outputStream() {
6968
return delegate;
7069
}
7170

71+
/**
72+
* Creates a default builder for {@link BlockingOutputStreamAsyncRequestBody}.
73+
*/
74+
public static Builder builder() {
75+
return new Builder();
76+
}
77+
7278
@Override
7379
public Optional<Long> contentLength() {
7480
return Optional.ofNullable(contentLength);
@@ -99,4 +105,41 @@ private void waitForSubscriptionIfNeeded() {
99105
throw new RuntimeException("Interrupted while waiting for subscription.", e);
100106
}
101107
}
108+
109+
public static final class Builder {
110+
private Duration subscribeTimeout;
111+
private Long contentLength;
112+
113+
private Builder() {
114+
}
115+
116+
/**
117+
* Defines how long it should wait for this AsyncRequestBody to be subscribed (to start streaming) before timing out.
118+
* By default, it's 10 seconds.
119+
*
120+
* <p>You may want to increase it if the request may not be executed right away.
121+
*
122+
* @param subscribeTimeout the timeout
123+
* @return Returns a reference to this object so that method calls can be chained together.
124+
*/
125+
public Builder subscribeTimeout(Duration subscribeTimeout) {
126+
this.subscribeTimeout = subscribeTimeout;
127+
return this;
128+
}
129+
130+
/**
131+
* The content length of the output stream.
132+
*
133+
* @param contentLength the content length
134+
* @return Returns a reference to this object so that method calls can be chained together.
135+
*/
136+
public Builder contentLength(Long contentLength) {
137+
this.contentLength = contentLength;
138+
return this;
139+
}
140+
141+
public BlockingOutputStreamAsyncRequestBody build() {
142+
return new BlockingOutputStreamAsyncRequestBody(this);
143+
}
144+
}
102145
}

core/sdk-core/src/test/java/software/amazon/awssdk/core/async/BlockingOutputStreamAsyncRequestBodyTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ public void outputStream_waitsForSubscription() throws IOException {
5050

5151
@Test
5252
@Timeout(10)
53-
public void outputStream_failsIfSubscriptionNeverComes() {
53+
public void outputStream_overrideSubscribeTimeout_failsIfSubscriptionNeverComes() {
5454
BlockingOutputStreamAsyncRequestBody requestBody =
55-
new BlockingOutputStreamAsyncRequestBody(0L, Duration.ofSeconds(1));
55+
BlockingOutputStreamAsyncRequestBody.builder().contentLength(0L).subscribeTimeout(Duration.ofSeconds(1)).build();
5656
assertThatThrownBy(requestBody::outputStream).hasMessageContaining("The service request was not made");
5757
}
5858

0 commit comments

Comments
 (0)