|
16 | 16 | package software.amazon.awssdk.transfer.s3.internal;
|
17 | 17 |
|
18 | 18 | import static software.amazon.awssdk.transfer.s3.internal.TransferConfigurationOption.DEFAULT_DELIMITER;
|
| 19 | +import static software.amazon.awssdk.transfer.s3.internal.TransferConfigurationOption.DEFAULT_DIRECTORY_TRANSFER_MAX_CONCURRENCY; |
19 | 20 | import static software.amazon.awssdk.transfer.s3.internal.TransferConfigurationOption.DEFAULT_PREFIX;
|
20 | 21 |
|
21 | 22 | import java.io.IOException;
|
|
24 | 25 | import java.nio.file.LinkOption;
|
25 | 26 | import java.nio.file.Path;
|
26 | 27 | import java.util.Collection;
|
27 |
| -import java.util.List; |
28 | 28 | import java.util.concurrent.CompletableFuture;
|
29 | 29 | import java.util.concurrent.CompletionException;
|
30 | 30 | import java.util.concurrent.ConcurrentLinkedQueue;
|
31 | 31 | import java.util.function.Function;
|
32 |
| -import java.util.stream.Collectors; |
33 | 32 | import java.util.stream.Stream;
|
34 | 33 | import software.amazon.awssdk.annotations.SdkInternalApi;
|
| 34 | +import software.amazon.awssdk.core.async.SdkPublisher; |
35 | 35 | import software.amazon.awssdk.core.exception.SdkClientException;
|
36 | 36 | import software.amazon.awssdk.services.s3.model.PutObjectRequest;
|
37 | 37 | import software.amazon.awssdk.transfer.s3.S3TransferManager;
|
@@ -90,23 +90,26 @@ private void doUploadDirectory(CompletableFuture<CompletedDirectoryUpload> retur
|
90 | 90 | validateDirectory(uploadDirectoryRequest);
|
91 | 91 |
|
92 | 92 | Collection<FailedFileUpload> failedFileUploads = new ConcurrentLinkedQueue<>();
|
93 |
| - List<CompletableFuture<CompletedFileUpload>> futures; |
94 | 93 |
|
95 |
| - try (Stream<Path> entries = listFiles(directory, uploadDirectoryRequest)) { |
96 |
| - futures = entries.map(path -> { |
97 |
| - CompletableFuture<CompletedFileUpload> future = uploadSingleFile(uploadDirectoryRequest, |
98 |
| - failedFileUploads, path); |
| 94 | + Stream<Path> stream = listFiles(directory, uploadDirectoryRequest); |
99 | 95 |
|
100 |
| - // Forward cancellation of the return future to all individual futures. |
101 |
| - CompletableFutureUtils.forwardExceptionTo(returnFuture, future); |
102 |
| - return future; |
103 |
| - }).collect(Collectors.toList()); |
104 |
| - } |
| 96 | + SdkPublisher<Path> iterablePublisher = SdkPublisher.fromIterable(() -> stream.iterator()) |
| 97 | + .doAfterOnCancel(() -> stream.close()) |
| 98 | + .doAfterOnError(t -> stream.close()) |
| 99 | + .doAfterOnComplete(() -> stream.close()); |
| 100 | + |
| 101 | + CompletableFuture<Void> allOfFutures = new CompletableFuture<>(); |
| 102 | + |
| 103 | + AsyncBufferingSubscriber<Path> bufferingSubscriber = |
| 104 | + new AsyncBufferingSubscriber<>(path -> uploadSingleFile(uploadDirectoryRequest, failedFileUploads, path), |
| 105 | + allOfFutures, DEFAULT_DIRECTORY_TRANSFER_MAX_CONCURRENCY); |
| 106 | + |
| 107 | + iterablePublisher.subscribe(bufferingSubscriber); |
| 108 | + CompletableFutureUtils.forwardExceptionTo(returnFuture, allOfFutures); |
105 | 109 |
|
106 |
| - CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) |
107 |
| - .whenComplete((r, t) -> returnFuture.complete(CompletedDirectoryUpload.builder() |
108 |
| - .failedTransfers(failedFileUploads) |
109 |
| - .build())); |
| 110 | + allOfFutures.whenComplete((r, t) -> returnFuture.complete(CompletedDirectoryUpload.builder() |
| 111 | + .failedTransfers(failedFileUploads) |
| 112 | + .build())); |
110 | 113 | }
|
111 | 114 |
|
112 | 115 | private void validateDirectory(UploadDirectoryRequest uploadDirectoryRequest) {
|
|
0 commit comments