This is an automated email from the ASF dual-hosted git repository.

SbloodyS pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new 8592557809 [Fix-18378] Fix list resources returned only 1000 records 
in s3 storage type (#18381)
8592557809 is described below

commit 8592557809d2d041d9d727371c090aef82e4dcae
Author: xiangzihao <[email protected]>
AuthorDate: Fri Jun 26 11:35:19 2026 +0800

    [Fix-18378] Fix list resources returned only 1000 records in s3 storage 
type (#18381)
---
 .../plugin/storage/s3/S3StorageOperator.java       | 35 +++++++++------
 .../plugin/storage/s3/S3StorageOperatorTest.java   | 52 ++++++++++++++++++++++
 2 files changed, 74 insertions(+), 13 deletions(-)

diff --git 
a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/main/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperator.java
 
b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/main/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperator.java
index 2f4954fe1c..df9b123f2b 100644
--- 
a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/main/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperator.java
+++ 
b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/main/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperator.java
@@ -65,12 +65,17 @@ public class S3StorageOperator extends 
AbstractStorageOperator implements Closea
     private final AmazonS3 s3Client;
 
     public S3StorageOperator(S3StorageProperties s3StorageProperties) {
-        super(s3StorageProperties.getResourceUploadPath());
-        bucketName = s3StorageProperties.getBucketName();
-        s3Client = 
AmazonS3ClientFactory.createAmazonS3Client(s3StorageProperties.getS3Configuration());
+        this(s3StorageProperties.getBucketName(), 
s3StorageProperties.getResourceUploadPath(),
+                
AmazonS3ClientFactory.createAmazonS3Client(s3StorageProperties.getS3Configuration()));
         exceptionWhenBucketNameNotExists(bucketName);
     }
 
+    S3StorageOperator(String bucketName, String resourceUploadPath, AmazonS3 
s3Client) {
+        super(resourceUploadPath);
+        this.bucketName = bucketName;
+        this.s3Client = s3Client;
+    }
+
     @Override
     public String getStorageBaseDirectory() {
         // All directory should end with File.separator
@@ -224,17 +229,21 @@ public class S3StorageOperator extends 
AbstractStorageOperator implements Closea
                 .withDelimiter("/")
                 .withPrefix(s3ResourceAbsolutePath);
 
-        ListObjectsV2Result listObjectsV2Result = 
s3Client.listObjectsV2(listObjectsV2Request);
         List<StorageEntity> storageEntities = new ArrayList<>();
-        storageEntities.addAll(listObjectsV2Result.getCommonPrefixes()
-                .stream()
-                .map(this::transformCommonPrefixToStorageEntity)
-                .collect(Collectors.toList()));
-        storageEntities.addAll(
-                listObjectsV2Result.getObjectSummaries().stream()
-                        .filter(s3ObjectSummary -> 
!s3ObjectSummary.getKey().equals(s3ResourceAbsolutePath))
-                        .map(this::transformS3ObjectToStorageEntity)
-                        .collect(Collectors.toList()));
+        ListObjectsV2Result listObjectsV2Result;
+        do {
+            listObjectsV2Result = s3Client.listObjectsV2(listObjectsV2Request);
+            storageEntities.addAll(listObjectsV2Result.getCommonPrefixes()
+                    .stream()
+                    .map(this::transformCommonPrefixToStorageEntity)
+                    .collect(Collectors.toList()));
+            storageEntities.addAll(
+                    listObjectsV2Result.getObjectSummaries().stream()
+                            .filter(s3ObjectSummary -> 
!s3ObjectSummary.getKey().equals(s3ResourceAbsolutePath))
+                            .map(this::transformS3ObjectToStorageEntity)
+                            .collect(Collectors.toList()));
+            
listObjectsV2Request.setContinuationToken(listObjectsV2Result.getNextContinuationToken());
+        } while (listObjectsV2Result.isTruncated());
 
         return storageEntities;
     }
diff --git 
a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/test/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperatorTest.java
 
b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/test/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperatorTest.java
index dc635cceb5..e5e5ca0aab 100644
--- 
a/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/test/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperatorTest.java
+++ 
b/dolphinscheduler-storage-plugin/dolphinscheduler-storage-s3/src/test/java/org/apache/dolphinscheduler/plugin/storage/s3/S3StorageOperatorTest.java
@@ -27,8 +27,10 @@ import 
org.apache.dolphinscheduler.plugin.storage.api.ResourceMetadata;
 import org.apache.dolphinscheduler.plugin.storage.api.StorageEntity;
 import org.apache.dolphinscheduler.spi.enums.ResourceType;
 
+import java.lang.reflect.Proxy;
 import java.nio.file.FileAlreadyExistsException;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Stream;
 
 import lombok.SneakyThrows;
@@ -46,6 +48,9 @@ import com.amazonaws.auth.AWSStaticCredentialsProvider;
 import com.amazonaws.auth.BasicAWSCredentials;
 import com.amazonaws.services.s3.AmazonS3;
 import com.amazonaws.services.s3.AmazonS3ClientBuilder;
+import com.amazonaws.services.s3.model.ListObjectsV2Request;
+import com.amazonaws.services.s3.model.ListObjectsV2Result;
+import com.amazonaws.services.s3.model.S3ObjectSummary;
 
 public class S3StorageOperatorTest {
 
@@ -259,6 +264,20 @@ public class S3StorageOperatorTest {
 
     }
 
+    @Test
+    public void testListStorageEntity_shouldFetchAllS3Pages() {
+        AtomicInteger listObjectsCallCount = new AtomicInteger();
+        AmazonS3 amazonS3 = createPagedAmazonS3Client(listObjectsCallCount);
+        S3StorageOperator storageOperator = new 
S3StorageOperator("dolphinscheduler",
+                "tmp/dolphinscheduler", amazonS3);
+
+        List<StorageEntity> storageEntities =
+                
storageOperator.listStorageEntity("tmp/dolphinscheduler/default/resources/largeDirectory");
+
+        assertThat(storageEntities).hasSize(1001);
+        assertThat(listObjectsCallCount.get()).isEqualTo(2);
+    }
+
     @Test
     public void testListStorageEntity_directoryNotExist() {
         List<StorageEntity> storageEntities =
@@ -302,4 +321,37 @@ public class S3StorageOperatorTest {
         }
     }
 
+    private AmazonS3 createPagedAmazonS3Client(AtomicInteger 
listObjectsCallCount) {
+        return (AmazonS3) Proxy.newProxyInstance(
+                AmazonS3.class.getClassLoader(),
+                new Class<?>[]{AmazonS3.class},
+                (proxy, method, args) -> {
+                    if (!"listObjectsV2".equals(method.getName())) {
+                        return null;
+                    }
+
+                    ListObjectsV2Request request = (ListObjectsV2Request) 
args[0];
+                    int callIndex = listObjectsCallCount.getAndIncrement();
+                    if (callIndex == 0) {
+                        assertThat(request.getContinuationToken()).isNull();
+                        return createListObjectsV2Result("next-page-token", 0, 
1000);
+                    }
+                    
assertThat(request.getContinuationToken()).isEqualTo("next-page-token");
+                    return createListObjectsV2Result(null, 1000, 1001);
+                });
+    }
+
+    private ListObjectsV2Result createListObjectsV2Result(String 
nextContinuationToken, int start, int end) {
+        ListObjectsV2Result listObjectsV2Result = new ListObjectsV2Result();
+        listObjectsV2Result.setTruncated(nextContinuationToken != null);
+        listObjectsV2Result.setNextContinuationToken(nextContinuationToken);
+        for (int i = start; i < end; i++) {
+            S3ObjectSummary s3ObjectSummary = new S3ObjectSummary();
+            s3ObjectSummary.setKey(String.format(
+                    
"tmp/dolphinscheduler/default/resources/largeDirectory/demo-%04d.sql", i));
+            listObjectsV2Result.getObjectSummaries().add(s3ObjectSummary);
+        }
+        return listObjectsV2Result;
+    }
+
 }

Reply via email to