github-actions[bot] commented on code in PR #66914:
URL: https://github.com/apache/doris/pull/66914#discussion_r3820887675


##########
fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergConnector.java:
##########
@@ -1525,6 +1581,10 @@ public java.util.logging.Logger getParentLogger() throws 
java.sql.SQLFeatureNotS
 
     @Override
     public void close() throws IOException {
+        // Release connector-owned cache references while the catalog objects 
are still available to classify
+        // and close per-table FileIO. Active statement borrowers retain their 
own references and defer the actual
+        // cleanup until their leases close.
+        invalidateAll();

Review Comment:
   [P1] Defer catalog teardown until active table leases finish. 
invalidateAll() releases only Doris's cache reference, but the following 
Glue/REST/S3Tables catalog close directly closes Iceberg's FileIOTracker or 
shared IO; those upstream owners are outside TableOwner.references, so an 
active ScopedBorrow is still poisoned despite the comment above. REST 401 
reauthentication similarly closes the old delegate without invalidating or 
generation-keying cached tables. Please make leases retain the catalog/delegate 
generation and retire it after its final borrower, then test connector close 
and 401 replacement with a real active lease.



##########
fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergStatementScope.java:
##########
@@ -83,6 +83,39 @@ static Table sharedTable(ConnectorSession session, String 
dbName, String tableNa
                 () -> snapshotReadTable(loader.get()));
     }
 
+    /**
+     * Statement-scoped variant for a table borrowed from {@link 
IcebergTableCache}. The memoized holder is
+     * {@link AutoCloseable}, so the engine's statement-scope teardown 
releases the borrower only after scan
+     * pumps have quiesced. Cache eviction and statement completion may happen 
in either order; the underlying
+     * FileIO is closed only after both owners release it.
+     */
+    static Table sharedBorrowedTable(ConnectorSession session, String dbName, 
String tableName,
+            Supplier<IcebergTableCache.TableLease> loader, Supplier<Table> 
unscopedLoader) {
+        if (session == null || session.getStatementScope() == 
ConnectorStatementScope.NONE) {

Review Comment:
   [P1] Do not bypass the enabled table cache for NONE sessions. 
PluginDrivenExternalTable.initSchema, row-count, and statistics loaders all use 
buildCrossStatementSession(), which forces NONE, so this production branch now 
calls the raw catalog loader even when the pre-PR positive-TTL cache exists. 
For Glue/S3Tables each load owns a new tracked FileIO; because this path has 
neither a lease nor an explicit close, cleanup falls back to Iceberg's weak-key 
tracker/GC and recreates the nondeterministic client retention this PR is meant 
to fix. Please preserve cache reuse and make the complete cross-statement 
operation own/close a lease (or equivalent), with production-shaped tests.



##########
fe/fe-connector/fe-connector-hudi/src/main/java/org/apache/doris/connector/hudi/HudiScanPlanProvider.java:
##########
@@ -294,30 +294,33 @@ basePath, inputFormat, serdeLib, columnNames, 
columnTypes, partitionFieldNames(m
         HoodieLocalEngineContext engineCtx = new 
HoodieLocalEngineContext(metaClient.getStorageConf());
         HoodieTableFileSystemView fsView = 
FileSystemViewManager.createInMemoryFileSystemView(
                 engineCtx, metaClient, metadataConfig);
+        try {
+            // Resolve partitions
+            List<String> partitionPaths = resolvePartitions(hudiHandle, 
metaClient);
 
-        // Resolve partitions
-        List<String> partitionPaths = resolvePartitions(hudiHandle, 
metaClient);
-
-        List<ConnectorScanRange> ranges = new ArrayList<>();
-        for (String partitionPath : partitionPaths) {
-            Map<String, String> partValues = parsePartitionValues(
-                    partitionPath, hudiHandle.getPartitionKeyNames());
+            List<ConnectorScanRange> ranges = new ArrayList<>();
+            for (String partitionPath : partitionPaths) {
+                Map<String, String> partValues = parsePartitionValues(
+                        partitionPath, hudiHandle.getPartitionKeyNames());
 
-            if (useNativeCowPath) {
-                collectCowSplits(fsView, partitionPath, queryInstant,
-                        basePath, partValues, ranges, schemaIdResolver);
-            } else {
-                collectMorSplits(fsView, partitionPath, queryInstant,
-                        basePath, inputFormat, serdeLib,
-                        columnNames, columnTypes, partValues, forceJni, 
ranges, schemaIdResolver);
+                if (useNativeCowPath) {
+                    collectCowSplits(fsView, partitionPath, queryInstant,
+                            basePath, partValues, ranges, schemaIdResolver);
+                } else {
+                    collectMorSplits(fsView, partitionPath, queryInstant,
+                            basePath, inputFormat, serdeLib,
+                            columnNames, columnTypes, partValues, forceJni, 
ranges, schemaIdResolver);
+                }
             }
-        }
 
-        LOG.info("Hudi scan planning: {}.{} type={} partitions={} splits={}",
-                hudiHandle.getDbName(), hudiHandle.getTableName(),
-                hudiHandle.getHudiTableType(), partitionPaths.size(), 
ranges.size());
+            LOG.info("Hudi scan planning: {}.{} type={} partitions={} 
splits={}",
+                    hudiHandle.getDbName(), hudiHandle.getTableName(),
+                    hudiHandle.getHudiTableType(), partitionPaths.size(), 
ranges.size());
 
-        return ranges;
+            return ranges;
+        } finally {
+            fsView.close();

Review Comment:
   [P2] Preserve the planning failure if cleanup also fails. Hudi 1.0.2's 
AbstractTableFileSystemView.close() wraps tableMetadata.close() failures in 
HoodieException, while this raw finally replaces any exception already thrown 
by partition/split planning; MORIncrementalRelation has the same pattern. 
Please use try-with-resources (or addSuppressed explicitly) for both views and 
cover success plus body-and-close failure paths. The new lifecycle test only 
exercises listAllPartitionPaths, so deleting either fsView.close still leaves 
it green.



##########
fe/fe-connector/fe-connector-hudi/pom.xml:
##########
@@ -258,6 +258,16 @@ under the License.
             <artifactId>junit-jupiter</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>

Review Comment:
   [P2] Keep connector tests free of Mockito. fe/fe-connector/AGENTS.md 
explicitly requires recording fakes and says connector POMs carry no mocking 
framework. This single HoodieTableMetadata.close() assertion introduces 
mockito-core and the additional Kryo test-classpath closure it needs. Please 
replace the mock with a recording fake or narrow lifecycle seam and remove both 
dependencies.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to