|
27 | 27 | import software.amazon.awssdk.core.exception.NonRetryableException;
|
28 | 28 | import software.amazon.awssdk.core.internal.io.SdkLengthAwareInputStream;
|
29 | 29 | import software.amazon.awssdk.core.internal.util.NoopSubscription;
|
| 30 | +import software.amazon.awssdk.utils.Validate; |
30 | 31 | import software.amazon.awssdk.utils.async.InputStreamConsumingPublisher;
|
31 | 32 |
|
32 | 33 | /**
|
|
37 | 38 | */
|
38 | 39 | @SdkPublicApi
|
39 | 40 | public final class BlockingInputStreamAsyncRequestBody implements AsyncRequestBody {
|
| 41 | + private static final Duration DEFAULT_SUBSCRIBE_TIMEOUT = Duration.ofSeconds(10); |
40 | 42 | private final InputStreamConsumingPublisher delegate = new InputStreamConsumingPublisher();
|
41 | 43 | private final CountDownLatch subscribedLatch = new CountDownLatch(1);
|
42 | 44 | private final AtomicBoolean subscribeCalled = new AtomicBoolean(false);
|
43 | 45 | private final Long contentLength;
|
44 | 46 | private final Duration subscribeTimeout;
|
45 | 47 |
|
46 |
| - BlockingInputStreamAsyncRequestBody(Long contentLength) { |
47 |
| - this(contentLength, Duration.ofSeconds(10)); |
| 48 | + BlockingInputStreamAsyncRequestBody(Builder builder) { |
| 49 | + this.contentLength = builder.contentLength; |
| 50 | + this.subscribeTimeout = Validate.isPositiveOrNull(builder.subscribeTimeout, "subscribeTimeout") != null ? |
| 51 | + builder.subscribeTimeout : |
| 52 | + DEFAULT_SUBSCRIBE_TIMEOUT; |
48 | 53 | }
|
49 | 54 |
|
50 |
| - BlockingInputStreamAsyncRequestBody(Long contentLength, Duration subscribeTimeout) { |
51 |
| - this.contentLength = contentLength; |
52 |
| - this.subscribeTimeout = subscribeTimeout; |
| 55 | + /** |
| 56 | + * Creates a default builder for {@link BlockingInputStreamAsyncRequestBody}. |
| 57 | + */ |
| 58 | + public static Builder builder() { |
| 59 | + return new Builder(); |
53 | 60 | }
|
54 | 61 |
|
55 | 62 | @Override
|
@@ -112,4 +119,41 @@ private void waitForSubscriptionIfNeeded() throws InterruptedException {
|
112 | 119 | + "BEFORE invoking doBlockingWrite if your caller is single-threaded.");
|
113 | 120 | }
|
114 | 121 | }
|
| 122 | + |
| 123 | + public static final class Builder { |
| 124 | + private Duration subscribeTimeout; |
| 125 | + private Long contentLength; |
| 126 | + |
| 127 | + private Builder() { |
| 128 | + } |
| 129 | + |
| 130 | + /** |
| 131 | + * Defines how long it should wait for this AsyncRequestBody to be subscribed (to start streaming) before timing out. |
| 132 | + * By default, it's 10 seconds. |
| 133 | + * |
| 134 | + * <p>You may want to increase it if the request may not be executed right away. |
| 135 | + * |
| 136 | + * @param subscribeTimeout the timeout |
| 137 | + * @return Returns a reference to this object so that method calls can be chained together. |
| 138 | + */ |
| 139 | + public Builder subscribeTimeout(Duration subscribeTimeout) { |
| 140 | + this.subscribeTimeout = subscribeTimeout; |
| 141 | + return this; |
| 142 | + } |
| 143 | + |
| 144 | + /** |
| 145 | + * The content length of the output stream. |
| 146 | + * |
| 147 | + * @param contentLength the content length |
| 148 | + * @return Returns a reference to this object so that method calls can be chained together. |
| 149 | + */ |
| 150 | + public Builder contentLength(Long contentLength) { |
| 151 | + this.contentLength = contentLength; |
| 152 | + return this; |
| 153 | + } |
| 154 | + |
| 155 | + public BlockingInputStreamAsyncRequestBody build() { |
| 156 | + return new BlockingInputStreamAsyncRequestBody(this); |
| 157 | + } |
| 158 | + } |
115 | 159 | }
|
0 commit comments