This is an automated email from the ASF dual-hosted git repository.
voonhous pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hudi.git
The following commit(s) were added to refs/heads/master by this push:
new f9c19c0c5b38 test(metadata): fix testReattemptOfFailedClusteringCommit
to simulate the crash before any metadata read (#19434)
f9c19c0c5b38 is described below
commit f9c19c0c5b38b361bb1d307791cf70eff92b61ee
Author: Y Ethan Guo <[email protected]>
AuthorDate: Fri Jul 31 03:23:04 2026 -0700
test(metadata): fix testReattemptOfFailedClusteringCommit to simulate the
crash before any metadata read (#19434)
---
.../hudi/client/TestJavaHoodieBackedMetadata.java | 29 +++++++++++++++++++---
.../hudi/functional/TestHoodieBackedMetadata.java | 29 +++++++++++++++++++---
2 files changed, 50 insertions(+), 8 deletions(-)
diff --git
a/hudi-client/hudi-java-client/src/test/java/org/apache/hudi/client/TestJavaHoodieBackedMetadata.java
b/hudi-client/hudi-java-client/src/test/java/org/apache/hudi/client/TestJavaHoodieBackedMetadata.java
index 776816420352..2588364e0451 100644
---
a/hudi-client/hudi-java-client/src/test/java/org/apache/hudi/client/TestJavaHoodieBackedMetadata.java
+++
b/hudi-client/hudi-java-client/src/test/java/org/apache/hudi/client/TestJavaHoodieBackedMetadata.java
@@ -2008,7 +2008,7 @@ public class TestJavaHoodieBackedMetadata extends
TestHoodieMetadataBase {
.withClusteringExecutionStrategyClass(JavaSortAndSizeExecutionStrategy.class.getName())
.build();
- HoodieWriteConfig newWriteConfig = getConfigBuilder(TRIP_EXAMPLE_SCHEMA,
HoodieIndex.IndexType.BLOOM, HoodieFailedWritesCleaningPolicy.EAGER)
+ HoodieWriteConfig newWriteConfig = getConfigBuilder(TRIP_EXAMPLE_SCHEMA,
HoodieIndex.IndexType.BLOOM, HoodieFailedWritesCleaningPolicy.LAZY)
.withClusteringConfig(clusteringConfig)
.withRollbackUsingMarkers(false)
.build();
@@ -2024,6 +2024,22 @@ public class TestJavaHoodieBackedMetadata extends
TestHoodieMetadataBase {
partitionFiles.getValue().stream().forEach(file ->
replacedFileIds.add(new HoodieFileGroupId(partitionFiles.getKey(),
file))));
+ // manually remove clustering completed instant from .hoodie folder to
mimic clustering
+ // succeeded in metadata table, but failed before committing to data
table. This must happen
+ // before any subsequent metadata-table read so that no reader ever sees
the first attempt's
+ // instant as committed, matching the crash scenario this test simulates.
+ FileCreateUtilsLegacy.deleteReplaceCommit(basePath, clusteringCommitTime);
+
+ // preconditions: clustering is pending on the data table while its
deltacommit is completed
+ // in the metadata table.
+ metaClient.reloadActiveTimeline();
+
assertFalse(metaClient.getActiveTimeline().filterCompletedInstants().containsInstant(clusteringCommitTime));
+
assertTrue(metaClient.getActiveTimeline().filterPendingClusteringTimeline().containsInstant(clusteringCommitTime));
+ HoodieTableMetaClient metadataMetaClient =
HoodieTestUtils.createMetaClient(
+ metaClient.getStorageConf(), getMetadataTableBasePath(basePath));
+ assertTrue(metadataMetaClient.getActiveTimeline().getDeltaCommitTimeline()
+ .filterCompletedInstants().containsInstant(clusteringCommitTime));
+
// trigger new write to mimic other writes succeeding before re-attempt.
newCommitTime = WriteClientTestUtils.createNewInstantTime();
WriteClientTestUtils.startCommitWithTime(client, newCommitTime);
@@ -2031,10 +2047,15 @@ public class TestJavaHoodieBackedMetadata extends
TestHoodieMetadataBase {
writeStatuses = client.insert(records, newCommitTime);
client.commit(newCommitTime, writeStatuses);
assertNoWriteErrors(writeStatuses);
- validateMetadata(client);
+ // ignore the first clustering attempt's uncommitted files when comparing
listings.
+ validateMetadata(client, Option.of(clusteringCommitTime));
+
+ // the new write must leave the pending clustering and its metadata-table
deltacommit intact.
+ metaClient.reloadActiveTimeline();
+
assertTrue(metaClient.getActiveTimeline().filterPendingClusteringTimeline().containsInstant(clusteringCommitTime));
+
assertTrue(metadataMetaClient.reloadActiveTimeline().getDeltaCommitTimeline()
+ .filterCompletedInstants().containsInstant(clusteringCommitTime));
- // manually remove clustering completed instant from .hoodie folder and to
mimic succeeded clustering in metadata table, but failed in data table.
- FileCreateUtilsLegacy.deleteReplaceCommit(basePath, clusteringCommitTime);
HoodieWriteMetadata<List<WriteStatus>> updatedClusterMetadata =
newClient.cluster(clusteringCommitTime, true);
metaClient.reloadActiveTimeline();
diff --git
a/hudi-spark-datasource/hudi-spark/src/test/java/org/apache/hudi/functional/TestHoodieBackedMetadata.java
b/hudi-spark-datasource/hudi-spark/src/test/java/org/apache/hudi/functional/TestHoodieBackedMetadata.java
index ec0d405fad91..9aa0b43fb949 100644
---
a/hudi-spark-datasource/hudi-spark/src/test/java/org/apache/hudi/functional/TestHoodieBackedMetadata.java
+++
b/hudi-spark-datasource/hudi-spark/src/test/java/org/apache/hudi/functional/TestHoodieBackedMetadata.java
@@ -2881,7 +2881,7 @@ public class TestHoodieBackedMetadata extends
TestHoodieMetadataBase {
.withClusteringSortColumns("_row_key").withInlineClustering(true)
.withClusteringTargetPartitions(0).withInlineClusteringNumCommits(1).build();
- HoodieWriteConfig newWriteConfig = getConfigBuilder(TRIP_EXAMPLE_SCHEMA,
HoodieIndex.IndexType.BLOOM, HoodieFailedWritesCleaningPolicy.EAGER)
+ HoodieWriteConfig newWriteConfig = getConfigBuilder(TRIP_EXAMPLE_SCHEMA,
HoodieIndex.IndexType.BLOOM, HoodieFailedWritesCleaningPolicy.LAZY)
.withClusteringConfig(clusteringConfig)
.withRollbackUsingMarkers(false)
.build();
@@ -2897,6 +2897,22 @@ public class TestHoodieBackedMetadata extends
TestHoodieMetadataBase {
partitionFiles.getValue().stream().forEach(file ->
replacedFileIds.add(new HoodieFileGroupId(partitionFiles.getKey(),
file))));
+ // manually remove clustering completed instant from .hoodie folder to
mimic clustering
+ // succeeded in metadata table, but failed before committing to data
table. This must happen
+ // before any subsequent metadata-table read so that no reader ever sees
the first attempt's
+ // instant as committed, matching the crash scenario this test simulates.
+ FileCreateUtilsLegacy.deleteReplaceCommit(basePath, clusteringCommitTime);
+
+ // preconditions: clustering is pending on the data table while its
deltacommit is completed
+ // in the metadata table.
+ metaClient.reloadActiveTimeline();
+
assertFalse(metaClient.getActiveTimeline().filterCompletedInstants().containsInstant(clusteringCommitTime));
+
assertTrue(metaClient.getActiveTimeline().filterPendingClusteringTimeline().containsInstant(clusteringCommitTime));
+ HoodieTableMetaClient metadataMetaClient =
HoodieTestUtils.createMetaClient(
+ metaClient.getStorageConf(), getMetadataTableBasePath(basePath));
+ assertTrue(metadataMetaClient.getActiveTimeline().getDeltaCommitTimeline()
+ .filterCompletedInstants().containsInstant(clusteringCommitTime));
+
// trigger new write to mimic other writes succeeding before re-attempt.
newCommitTime = "0000003";
WriteClientTestUtils.startCommitWithTime(client, newCommitTime);
@@ -2904,10 +2920,15 @@ public class TestHoodieBackedMetadata extends
TestHoodieMetadataBase {
writeStatuses = client.insert(jsc.parallelize(records, 1),
newCommitTime).collect();
assertTrue(client.commit(newCommitTime, jsc.parallelize(writeStatuses),
Option.empty(), COMMIT_ACTION, Collections.emptyMap(), Option.empty()));
assertNoWriteErrors(writeStatuses);
- validateMetadata(client);
+ // ignore the first clustering attempt's uncommitted files when comparing
listings.
+ validateMetadata(client, Option.of(clusteringCommitTime));
+
+ // the new write must leave the pending clustering and its metadata-table
deltacommit intact.
+ metaClient.reloadActiveTimeline();
+
assertTrue(metaClient.getActiveTimeline().filterPendingClusteringTimeline().containsInstant(clusteringCommitTime));
+
assertTrue(metadataMetaClient.reloadActiveTimeline().getDeltaCommitTimeline()
+ .filterCompletedInstants().containsInstant(clusteringCommitTime));
- // manually remove clustering completed instant from .hoodie folder and to
mimic succeeded clustering in metadata table, but failed in data table.
- FileCreateUtilsLegacy.deleteReplaceCommit(basePath, clusteringCommitTime);
HoodieWriteMetadata<JavaRDD<WriteStatus>> updatedClusterMetadata =
newClient.cluster(clusteringCommitTime, true);
metaClient.reloadActiveTimeline();