[HUDI-2533] New option for hoodieClusteringJob to check, rollback and re-execute the last failed clustering job (#3765)
* coding finished and need to do uts * add uts * code review * code review Co-authored-by: yuezhang <yuezhang@freewheel.tv>
This commit is contained in:
@@ -139,9 +139,13 @@ public class TestHoodieDeltaStreamer extends HoodieDeltaStreamerTestBase {
|
||||
return new HoodieDeltaStreamer(cfg, jsc);
|
||||
}
|
||||
|
||||
protected HoodieClusteringJob initialHoodieClusteringJob(String tableBasePath, String clusteringInstantTime, boolean runSchedule, String scheduleAndExecute) {
|
||||
protected HoodieClusteringJob initialHoodieClusteringJob(String tableBasePath, String clusteringInstantTime, Boolean runSchedule, String scheduleAndExecute) {
|
||||
return initialHoodieClusteringJob(tableBasePath, clusteringInstantTime, runSchedule, scheduleAndExecute, null);
|
||||
}
|
||||
|
||||
protected HoodieClusteringJob initialHoodieClusteringJob(String tableBasePath, String clusteringInstantTime, Boolean runSchedule, String scheduleAndExecute, Boolean retryLastFailedClusteringJob) {
|
||||
HoodieClusteringJob.Config scheduleClusteringConfig = buildHoodieClusteringUtilConfig(tableBasePath,
|
||||
clusteringInstantTime, runSchedule, scheduleAndExecute);
|
||||
clusteringInstantTime, runSchedule, scheduleAndExecute, retryLastFailedClusteringJob);
|
||||
return new HoodieClusteringJob(jsc, scheduleClusteringConfig);
|
||||
}
|
||||
|
||||
@@ -844,20 +848,24 @@ public class TestHoodieDeltaStreamer extends HoodieDeltaStreamerTestBase {
|
||||
|
||||
private HoodieClusteringJob.Config buildHoodieClusteringUtilConfig(String basePath,
|
||||
String clusteringInstantTime,
|
||||
boolean runSchedule) {
|
||||
return buildHoodieClusteringUtilConfig(basePath, clusteringInstantTime, runSchedule, null);
|
||||
Boolean runSchedule) {
|
||||
return buildHoodieClusteringUtilConfig(basePath, clusteringInstantTime, runSchedule, null, null);
|
||||
}
|
||||
|
||||
private HoodieClusteringJob.Config buildHoodieClusteringUtilConfig(String basePath,
|
||||
String clusteringInstantTime,
|
||||
boolean runSchedule,
|
||||
String runningMode) {
|
||||
Boolean runSchedule,
|
||||
String runningMode,
|
||||
Boolean retryLastFailedClusteringJob) {
|
||||
HoodieClusteringJob.Config config = new HoodieClusteringJob.Config();
|
||||
config.basePath = basePath;
|
||||
config.clusteringInstantTime = clusteringInstantTime;
|
||||
config.runSchedule = runSchedule;
|
||||
config.propsFilePath = dfsBasePath + "/clusteringjob.properties";
|
||||
config.runningMode = runningMode;
|
||||
if (retryLastFailedClusteringJob != null) {
|
||||
config.retryLastFailedClusteringJob = retryLastFailedClusteringJob;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -933,6 +941,52 @@ public class TestHoodieDeltaStreamer extends HoodieDeltaStreamerTestBase {
|
||||
});
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void testAsyncClusteringJobWithRetry(boolean retryLastFailedClusteringJob) throws Exception {
|
||||
String tableBasePath = dfsBasePath + "/asyncClustering3";
|
||||
|
||||
// ingest data
|
||||
int totalRecords = 3000;
|
||||
HoodieDeltaStreamer.Config cfg = TestHelpers.makeConfig(tableBasePath, WriteOperationType.INSERT);
|
||||
cfg.continuousMode = false;
|
||||
cfg.tableType = HoodieTableType.COPY_ON_WRITE.name();
|
||||
cfg.configs.addAll(getAsyncServicesConfigs(totalRecords, "false", "false", "0", "false", "0"));
|
||||
HoodieDeltaStreamer ds = new HoodieDeltaStreamer(cfg, jsc);
|
||||
ds.sync();
|
||||
|
||||
// assert ingest successful
|
||||
TestHelpers.assertAtLeastNCommits(1, tableBasePath, dfs);
|
||||
|
||||
// schedule a clustering job to build a clustering plan
|
||||
HoodieClusteringJob schedule = initialHoodieClusteringJob(tableBasePath, null, false, "schedule");
|
||||
schedule.cluster(0);
|
||||
|
||||
// do another ingestion
|
||||
HoodieDeltaStreamer ds2 = new HoodieDeltaStreamer(cfg, jsc);
|
||||
ds2.sync();
|
||||
|
||||
// convert clustering request into inflight, Simulate the last clustering failed scenario
|
||||
HoodieTableMetaClient meta = HoodieTableMetaClient.builder().setConf(dfs.getConf()).setBasePath(tableBasePath).build();
|
||||
List<HoodieInstant> hoodieClusteringInstants = meta.getActiveTimeline().filterPendingReplaceTimeline().getInstants().collect(Collectors.toList());
|
||||
HoodieInstant clusteringRequest = hoodieClusteringInstants.get(0);
|
||||
HoodieInstant hoodieInflightInstant = meta.getActiveTimeline().transitionReplaceRequestedToInflight(clusteringRequest, Option.empty());
|
||||
|
||||
// trigger a scheduleAndExecute clustering job
|
||||
// when retryFailedClustering true => will rollback and re-execute failed clustering plan with same instant timestamp.
|
||||
// when retryFailedClustering false => will make and execute a new clustering plan with new instant timestamp.
|
||||
HoodieClusteringJob scheduleAndExecute = initialHoodieClusteringJob(tableBasePath, null, false, "scheduleAndExecute", retryLastFailedClusteringJob);
|
||||
scheduleAndExecute.cluster(0);
|
||||
|
||||
String completeClusteringTimeStamp = meta.getActiveTimeline().reload().getCompletedReplaceTimeline().lastInstant().get().getTimestamp();
|
||||
|
||||
if (retryLastFailedClusteringJob) {
|
||||
assertEquals(clusteringRequest.getTimestamp(), completeClusteringTimeStamp);
|
||||
} else {
|
||||
assertFalse(clusteringRequest.getTimestamp().equalsIgnoreCase(completeClusteringTimeStamp));
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"schedule", "execute", "scheduleAndExecute"})
|
||||
public void testHoodieAsyncClusteringJobWithScheduleAndExecute(String runningMode) throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user