-
Notifications
You must be signed in to change notification settings - Fork 624
HDDS-12914. Validate AWS S3 Transfer Manager Resumable File Download #8455
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
eb0b5e5
f1afc91
c39746e
5494a60
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -63,6 +63,7 @@ | |||
| import org.junit.jupiter.api.io.TempDir; | ||||
| import software.amazon.awssdk.core.ResponseBytes; | ||||
| import software.amazon.awssdk.core.sync.RequestBody; | ||||
| import software.amazon.awssdk.services.s3.S3AsyncClient; | ||||
| import software.amazon.awssdk.services.s3.S3Client; | ||||
| import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadResponse; | ||||
| import software.amazon.awssdk.services.s3.model.CompletedMultipartUpload; | ||||
|
|
@@ -83,6 +84,10 @@ | |||
| import software.amazon.awssdk.services.s3.model.Tagging; | ||||
| import software.amazon.awssdk.services.s3.model.UploadPartRequest; | ||||
| import software.amazon.awssdk.services.s3.model.UploadPartResponse; | ||||
| import software.amazon.awssdk.transfer.s3.S3TransferManager; | ||||
| import software.amazon.awssdk.transfer.s3.model.DownloadFileRequest; | ||||
| import software.amazon.awssdk.transfer.s3.model.FileDownload; | ||||
| import software.amazon.awssdk.transfer.s3.model.ResumableFileDownload; | ||||
|
|
||||
| /** | ||||
| * This is an abstract class to test the AWS Java S3 SDK operations. | ||||
|
|
@@ -103,6 +108,7 @@ public abstract class AbstractS3SDKV2Tests extends OzoneTestBase { | |||
|
|
||||
| private static MiniOzoneCluster cluster = null; | ||||
| private static S3Client s3Client = null; | ||||
| private static S3AsyncClient s3AsyncClient = null; | ||||
|
|
||||
| /** | ||||
| * Create a MiniOzoneCluster with S3G enabled for testing. | ||||
|
|
@@ -117,6 +123,7 @@ static void startCluster(OzoneConfiguration conf) throws Exception { | |||
| .build(); | ||||
| cluster.waitForClusterToBeReady(); | ||||
| s3Client = new S3ClientFactory(s3g.getConf()).createS3ClientV2(); | ||||
| s3AsyncClient = new S3ClientFactory(s3g.getConf()).createS3AsyncClientV2(); | ||||
| } | ||||
|
|
||||
| /** | ||||
|
|
@@ -340,6 +347,45 @@ public void testLowLevelMultipartUpload(@TempDir Path tempDir) throws Exception | |||
| assertEquals(userMetadata, headObjectResponse.metadata()); | ||||
| } | ||||
|
|
||||
| @Test | ||||
| public void testResumableDownloadWithEtagMismatch() throws Exception { | ||||
| // Arrange | ||||
| final String bucketName = getBucketName("resumable"); | ||||
| final String keyName = getKeyName("resumable"); | ||||
| final String fileContent = "This is a test file for resumable download."; | ||||
| s3Client.createBucket(b -> b.bucket(bucketName)); | ||||
| s3Client.putObject(b -> b.bucket(bucketName).key(keyName), RequestBody.fromString(fileContent)); | ||||
|
|
||||
| // Prepare a temp file for download | ||||
| Path tempDownloadPath = Files.createTempFile("downloaded", ".txt"); | ||||
| File downloadFile = tempDownloadPath.toFile(); | ||||
|
|
||||
| // Set up S3TransferManager | ||||
| try (S3TransferManager transferManager = | ||||
| S3TransferManager.builder().s3Client(s3AsyncClient).build()) { | ||||
|
|
||||
| // First download | ||||
| DownloadFileRequest downloadRequest = DownloadFileRequest.builder() | ||||
| .getObjectRequest(b -> b.bucket(bucketName).key(keyName)) | ||||
| .destination(downloadFile.toPath()) | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: can use Line 363 in c39746e
Also, please rename |
||||
| .build(); | ||||
| FileDownload download = transferManager.downloadFile(downloadRequest); | ||||
| ResumableFileDownload resumableFileDownload = download.pause(); | ||||
|
|
||||
| // Simulate etag mismatch by modifying the file in S3 | ||||
| final String newContent = "This is new content to cause etag mismatch."; | ||||
| s3Client.putObject(b -> b.bucket(bucketName).key(keyName), RequestBody.fromString(newContent)); | ||||
|
|
||||
| // Resume download | ||||
| FileDownload resumedDownload = transferManager.resumeDownloadFile(resumableFileDownload); | ||||
| resumedDownload.completionFuture().get(); | ||||
|
|
||||
| String downloadedContent = new String(Files.readAllBytes(downloadFile.toPath()), StandardCharsets.UTF_8); | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: also use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the review @adoroszlai , update for both. |
||||
| assertEquals(newContent, downloadedContent); | ||||
| assertTrue(downloadFile.delete()); | ||||
| } | ||||
| } | ||||
|
|
||||
| private String getBucketName() { | ||||
| return getBucketName(""); | ||||
| } | ||||
|
|
||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review @peterxcli , update the PR.