nsivabalan commented on code in PR #19033:
URL: https://github.com/apache/hudi/pull/19033#discussion_r3737119697


##########
hudi-sync/hudi-hive-sync/src/main/java/org/apache/hudi/hive/ddl/HiveQueryDDLExecutor.java:
##########
@@ -209,21 +217,57 @@ public void dropPartitionsToTable(String tableName, 
List<String> partitionsToDro
 
     log.info("Drop partitions {} on {}", partitionsToDrop.size(), tableName);
     try {
-      for (String dropPartition : partitionsToDrop) {
-        if (HivePartitionUtil.partitionExists(metaStoreClient, tableName, 
dropPartition, partitionValueExtractor,
-            config)) {
-          String partitionClause =
-              HivePartitionUtil.getPartitionClauseForDrop(dropPartition, 
partitionValueExtractor, config);
-          metaStoreClient.dropPartition(databaseName, tableName, 
partitionClause, false);
-        }
-        log.info("Drop partition {} on {}", dropPartition, tableName);
-      }
+      int batchSyncPartitionNum = 
config.getIntOrDefault(HIVE_BATCH_SYNC_PARTITION_NUM);
+      List<List<String>> batches = CollectionUtils.batches(partitionsToDrop, 
batchSyncPartitionNum);
+      runDropBatches(tableName, batches);
     } catch (Exception e) {
       log.error("{} drop partition failed", tableId(databaseName, tableName), 
e);
       throw new HoodieHiveSyncException(tableId(databaseName, tableName) + " 
drop partition failed", e);
     }
   }
 
+  /**
+   * Drops partitions one batch at a time. When {@link #metaStoreClientPool} 
is present,
+   * batches fan out across the pool's worker threads (each borrowing an 
independent
+   * IMetaStoreClient); otherwise batches are dispatched sequentially against 
the
+   * session client. Hive has no batch-drop primitive that matches 
dropPartition's
+   * semantics, so each worker still iterates its chunk one partition at a 
time — the
+   * win is fanning chunks across independent Thrift clients.
+   *
+   * <p>First-error semantics come from {@link ParallelDispatch}, shared with
+   * {@code HiveDriverPool}: the first failure is rethrown, batches that have 
not started
+   * are stopped via the task-side abort flag, and later failures are logged 
at WARN.
+   */
+  private void runDropBatches(String tableName, List<List<String>> batches) 
throws Exception {
+    if (!metaStoreClientPool.isPresent()) {
+      for (List<String> batch : batches) {
+        applyDropBatch(metaStoreClient, tableName, batch);
+      }
+      return;
+    }
+    IMetaStoreClientPool pool = metaStoreClientPool.get();
+    pool.awaitAll(
+        pool.dispatchAll(batches, (client, batch) -> applyDropBatch(client, 
tableName, batch)),
+        "drop partition");
+  }
+
+  private void applyDropBatch(IMetaStoreClient client, String tableName, 
List<String> batch) throws Exception {
+    int dropped = 0;
+    for (String dropPartition : batch) {
+      if (HivePartitionUtil.partitionExists(client, tableName, dropPartition,

Review Comment:
   Filed as a nit, but I agree with your read that it is more than that — this 
is the data-loss-shaped one. Went with your second suggestion (extract on the 
calling thread before fan-out) rather than documenting the requirement, in 
3a1694a.
   
   Confirmed it was real before fixing it. A test that records the thread of 
every `extractPartitionValuesInPath` call, with a 4-client pool and 16 
partitions, fails on the old code with:
   
   ```
   expected: <[main]>
    but was: <[hudi-hive-sync-pool-1-1, hudi-hive-sync-pool-1-2,
               hudi-hive-sync-pool-1-3, hudi-hive-sync-pool-1-4, main]>
   ```
   
   All four workers were in the shared extractor concurrently, exactly as you 
described.
   
   The fix resolves each partition once on the calling thread into an immutable 
carrier (path + values + drop clause) and fans out only that. Three side 
benefits beyond removing the concurrency assumption:
   
   - **Halves the extractor calls.** `partitionExists` and 
`getPartitionClauseForDrop` were each extracting the same partition separately; 
they now share one result.
   - **Fails before the first drop.** A malformed partition previously threw 
partway through the batch, after some partitions had already been dropped. It 
now fails ahead of any drop — same `HoodieHiveSyncException`, just earlier, 
which matters for a destructive operation.
   - **`HMSDDLExecutor` is untouched.** `HivePartitionUtil` gained overloads 
taking pre-extracted values and the existing signatures delegate to them, so 
the sequential HMS path keeps its current behaviour.
   
   New test: 
`TestDropPartitionExtractorThreading#extractorIsNeverInvokedFromAPoolWorker`. 
It lives in `hive.util` rather than beside the executor because it needs the 
package-private `IMetaStoreClientPool` constructor that accepts pre-built 
clients. It also asserts the drops actually reached the pool, so it cannot pass 
by silently never fanning out.



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