Skip to content

Commit 62d3428

Browse files
committed
filter deleted partition
1 parent 74a5fb0 commit 62d3428

2 files changed

Lines changed: 29 additions & 0 deletions

File tree

hudi-client/hudi-client-common/src/main/java/org/apache/hudi/table/action/ttl/strategy/KeepByEventTimeStrategy.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,29 @@ protected List<String> getExpiredPartitionsForTimeStrategy(List<String> partitio
161161
return partitionPathsForTTL.stream().parallel()
162162
.filter(path -> isPartitionExpiredByEventTime(
163163
path, formatter, timeSegStartIndex, segCount, cutoffMillis, shouldDeleteHiveDefaultPartition, hiveStylePartitioning))
164+
// A partition emptied by a previous TTL replace commit keeps showing up in
165+
// getAllPartitionPaths() until the cleaner physically removes it, and its event time is
166+
// derived from the (unchanged) path, so it would be re-selected on every batch -- issuing
167+
// an empty replace commit each time and never converging. Keep only partitions that still
168+
// have a live file slice so the strategy is idempotent, mirroring KeepByTimeStrategy which
169+
// keys off the surviving slices' last commit time and thus naturally skips deleted ones.
170+
.filter(this::hasLiveFileSlice)
164171
.collect(Collectors.toList());
165172
}
166173

174+
/**
175+
* Whether the partition still has at least one live file slice as of {@code instantTime}.
176+
* File groups replaced by an earlier TTL delete are excluded by the file system view, so an
177+
* already-deleted partition returns {@code false} here even while its directory lingers on
178+
* storage awaiting the cleaner.
179+
*/
180+
private boolean hasLiveFileSlice(String partitionPath) {
181+
return hoodieTable.getHoodieView()
182+
.getLatestFileSlicesBeforeOrOn(partitionPath, instantTime, true)
183+
.findAny()
184+
.isPresent();
185+
}
186+
167187
/**
168188
* Number of '/'-separated path segments the configured format occupies.
169189
* Example: {@code yyyy-MM-dd/HH} -> 2.

hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestPartitionTTLManagement.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,15 @@ public void testKeepByEventTime() {
185185
Assertions.assertEquals(Sets.newHashSet(partitions[0], partitions[1]),
186186
result.getPartitionToReplaceFileIds().keySet());
187187
Assertions.assertEquals(10, readRecords(partitions).size());
188+
189+
// Idempotency: the partitions we just replaced still linger in getAllPartitionPaths() until
190+
// the cleaner runs, and their event time is derived from the (unchanged) path. Without the
191+
// live-file-slice guard they would be re-selected here, producing an endless stream of empty
192+
// replace commits. A second run must find nothing to delete.
193+
String instantTime2 = client.startDeletePartitionCommit(metaClient);
194+
HoodieWriteResult result2 = client.managePartitionTTL(instantTime2);
195+
Assertions.assertTrue(result2.getPartitionToReplaceFileIds().isEmpty(),
196+
"Already-deleted partitions must not be re-selected on the next TTL batch");
188197
}
189198
}
190199

0 commit comments

Comments
 (0)