roryqi commented on code in PR #11364:
URL: https://github.com/apache/gravitino/pull/11364#discussion_r3345581301


##########
iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/dispatcher/IcebergCleanupHelper.java:
##########
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.iceberg.service.dispatcher;
+
+import java.util.Optional;
+import org.apache.gravitino.GravitinoEnv;
+import org.apache.gravitino.NameIdentifier;
+import 
org.apache.gravitino.iceberg.service.authorization.IcebergRESTServerContext;
+import org.apache.gravitino.iceberg.service.cleanup.IcebergCleanupManager;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.exceptions.AlreadyExistsException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Request-path helpers shared by the table and namespace executors for async 
table purge. */
+final class IcebergCleanupHelper {
+
+  private static final Logger LOG = 
LoggerFactory.getLogger(IcebergCleanupHelper.class);
+
+  private IcebergCleanupHelper() {}
+
+  /**
+   * Returns the catalog entity id for {@code catalogName}. The catalog is 
already loaded for the
+   * current request, so this reads its in-memory entity without an extra 
entity-store lookup.
+   */
+  static long catalogId(String catalogName) {
+    String metalake = IcebergRESTServerContext.getInstance().metalakeName();
+    return GravitinoEnv.getInstance()
+        .catalogManager()
+        .loadCatalogAndWrap(NameIdentifier.of(metalake, catalogName))
+        .catalog()
+        .entity()
+        .id();
+  }
+
+  /**
+   * Fails a create or register with {@code 409} while a cleanup job still 
holds the identifier.
+   * Reusing the name before its files are gone would let the new table share 
the old table's
+   * storage prefix. A name with no resolvable catalog entity cannot have a 
cleanup job, so it stays
+   * usable.
+   */
+  static void rejectIfBeingPurged(
+      Optional<IcebergCleanupManager> cleanupManager,
+      String catalogName,
+      Namespace namespace,
+      String tableName) {
+    if (!cleanupManager.isPresent()) {

Review Comment:
   Done — switched to `cleanupManager.isEmpty()` in eaf27018b.



##########
iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/dispatcher/IcebergTableOperationExecutor.java:
##########
@@ -110,15 +121,38 @@ public LoadTableResponse updateTable(
   @Override
   public void dropTable(
       IcebergRequestContext context, TableIdentifier tableIdentifier, boolean 
purgeRequested) {
-    if (purgeRequested) {
-      icebergCatalogWrapperManager
-          .getCatalogWrapper(context.catalogName())
-          .purgeTable(tableIdentifier);
-    } else {
-      icebergCatalogWrapperManager
-          .getCatalogWrapper(context.catalogName())
-          .dropTable(tableIdentifier);
+    IcebergCatalogWrapper wrapper =
+        icebergCatalogWrapperManager.getCatalogWrapper(context.catalogName());
+    if (!purgeRequested) {
+      wrapper.dropTable(tableIdentifier);
+      return;
+    }
+
+    // Async cleanup is opt-in per request and only wired in auxiliary mode; 
otherwise purge inline.
+    if (!context.asyncPurge()) {
+      wrapper.purgeTable(tableIdentifier);
+      return;
     }
+
+    cleanupManager.ifPresentOrElse(

Review Comment:
   Yes. `cleanupManager` is only present in auxiliary mode. A request can still 
ask for async purge in standalone mode, where the manager is empty — in that 
case the `ifPresentOrElse` else-branch falls back to synchronous `purgeTable` 
rather than failing the request. I added a comment making this explicit in 
eaf27018b.



##########
iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/RESTService.java:
##########
@@ -119,9 +123,25 @@ protected javax.servlet.Filter 
createAuthenticationFilter() {
             skipAuthorizationForRestBackend,
             icebergCatalogWrapperManager);
     this.icebergMetricsManager = new IcebergMetricsManager(icebergConfig);
+    if (auxMode) {
+      // Async cleanup reuses the entity store's shared relational backend 
(connection pool +
+      // per-backend SQL), which is only available when running embedded in 
the Gravitino server
+      // (auxiliary mode). In standalone mode the cleanup manager stays empty 
and purge requests
+      // fall back to synchronous purge.
+      this.cleanupManager =
+          Optional.of(
+              new IcebergCleanupManager(
+                  new 
IcebergCleanupJobStore(GravitinoEnv.getInstance().idGenerator()),
+                  icebergConfig));
+    } else {
+      this.cleanupManager = Optional.empty();
+      LOG.info(
+          "Async Iceberg table cleanup is only available in auxiliary mode; "
+              + "purge requests fall back to synchronous purge.");

Review Comment:
   Good catch — updated the message to "...purge requests with async mode will 
fall back to synchronous purge." in eaf27018b.



-- 
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]

Reply via email to