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

JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new 53fd1c9fb0 [fs] Delegate listFilesIterative through RESTTokenFileIO 
(#9071)
53fd1c9fb0 is described below

commit 53fd1c9fb04c120c0d8eccd9eb0d44cee43b1c12
Author: tonymtu <[email protected]>
AuthorDate: Thu Aug 6 22:13:26 2026 +0800

    [fs] Delegate listFilesIterative through RESTTokenFileIO (#9071)
---
 .../org/apache/paimon/rest/RESTTokenFileIO.java    |  8 ++++
 .../apache/paimon/rest/RESTTokenFileIOTest.java    | 52 ++++++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git 
a/paimon-common/src/main/java/org/apache/paimon/rest/RESTTokenFileIO.java 
b/paimon-common/src/main/java/org/apache/paimon/rest/RESTTokenFileIO.java
index 73b5541d3c..fb210dda43 100644
--- a/paimon-common/src/main/java/org/apache/paimon/rest/RESTTokenFileIO.java
+++ b/paimon-common/src/main/java/org/apache/paimon/rest/RESTTokenFileIO.java
@@ -25,6 +25,7 @@ import org.apache.paimon.fs.FileIO;
 import org.apache.paimon.fs.FileStatus;
 import org.apache.paimon.fs.Path;
 import org.apache.paimon.fs.PositionOutputStream;
+import org.apache.paimon.fs.RemoteIterator;
 import org.apache.paimon.fs.SeekableInputStream;
 import org.apache.paimon.fs.TwoPhaseOutputStream;
 import org.apache.paimon.options.ConfigOption;
@@ -132,6 +133,13 @@ public class RESTTokenFileIO implements FileIO {
         return fileIO().listStatus(path);
     }
 
+    @Override
+    public RemoteIterator<FileStatus> listFilesIterative(Path path, boolean 
recursive)
+            throws IOException {
+        // the interface default would hide the inner FileIO's iterative 
listing override
+        return fileIO().listFilesIterative(path, recursive);
+    }
+
     @Override
     public boolean exists(Path path) throws IOException {
         return fileIO().exists(path);
diff --git 
a/paimon-common/src/test/java/org/apache/paimon/rest/RESTTokenFileIOTest.java 
b/paimon-common/src/test/java/org/apache/paimon/rest/RESTTokenFileIOTest.java
index 42e1746700..9bab3e1a89 100644
--- 
a/paimon-common/src/test/java/org/apache/paimon/rest/RESTTokenFileIOTest.java
+++ 
b/paimon-common/src/test/java/org/apache/paimon/rest/RESTTokenFileIOTest.java
@@ -23,7 +23,9 @@ import org.apache.paimon.catalog.Identifier;
 import org.apache.paimon.data.BlobDescriptor;
 import org.apache.paimon.fs.FileIO;
 import org.apache.paimon.fs.FileIOLoader;
+import org.apache.paimon.fs.FileStatus;
 import org.apache.paimon.fs.Path;
+import org.apache.paimon.fs.RemoteIterator;
 import org.apache.paimon.options.Options;
 import org.apache.paimon.rest.responses.GetTableTokenResponse;
 
@@ -112,4 +114,54 @@ class RESTTokenFileIOTest {
         // the interface default would have written a temp file and renamed it 
instead
         verify(delegate, never()).rename(any(), any());
     }
+
+    @Test
+    void testListFilesIterativeReachesInnerOverride() throws IOException {
+        Path tableRoot = new Path("oss://bucket/table");
+        FileIO delegate = mock(FileIO.class);
+        FileIOLoader loader = mock(FileIOLoader.class);
+        when(loader.load(any())).thenReturn(delegate);
+        when(loader.getScheme()).thenReturn("oss");
+        RESTApi api = mock(RESTApi.class);
+        Identifier identifier = Identifier.create("db", "table");
+        // a unique token, so the static token-keyed FileIO cache cannot serve 
another test's
+        // delegate
+        when(api.loadTableToken(identifier))
+                .thenReturn(
+                        new GetTableTokenResponse(
+                                Collections.singletonMap("token", 
UUID.randomUUID().toString()),
+                                Long.MAX_VALUE));
+        RESTTokenFileIO fileIO =
+                new RESTTokenFileIO(
+                        CatalogContext.create(new Options(), loader, null),
+                        api,
+                        identifier,
+                        tableRoot);
+        FileStatus status = mock(FileStatus.class);
+        RemoteIterator<FileStatus> iterator =
+                new RemoteIterator<FileStatus>() {
+                    private boolean emitted;
+
+                    @Override
+                    public boolean hasNext() {
+                        return !emitted;
+                    }
+
+                    @Override
+                    public FileStatus next() {
+                        emitted = true;
+                        return status;
+                    }
+                };
+        when(delegate.listFilesIterative(tableRoot, 
false)).thenReturn(iterator);
+
+        RemoteIterator<FileStatus> actual = 
fileIO.listFilesIterative(tableRoot, false);
+
+        assertThat(actual.hasNext()).isTrue();
+        assertThat(actual.next()).isSameAs(status);
+        assertThat(actual.hasNext()).isFalse();
+        verify(delegate).listFilesIterative(tableRoot, false);
+        // the interface default would construct its own iterator backed by 
listStatus
+        verify(delegate, never()).listStatus(any());
+    }
 }

Reply via email to