Wenjun Ruan
6 days ago
committed by
GitHub
9 changed files with 2 additions and 1712 deletions
@ -1,76 +0,0 @@
|
||||
/* |
||||
* 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.dolphinscheduler.common.utils; |
||||
|
||||
import org.apache.commons.beanutils.BeanMap; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.LinkedHashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* Provides utility methods and decorators for {@link Collection} instances. |
||||
* <p> |
||||
* Various utility methods might put the input objects into a Set/Map/Bag. In case |
||||
* the input objects override {@link Object#equals(Object)}, it is mandatory that |
||||
* the general contract of the {@link Object#hashCode()} method is maintained. |
||||
* <p> |
||||
* NOTE: From 4.0, method parameters will take {@link Iterable} objects when possible. |
||||
* |
||||
* @version $Id: CollectionUtils.java 1686855 2015-06-22 13:00:27Z tn $ |
||||
* @since 1.0 |
||||
*/ |
||||
public class CollectionUtils { |
||||
|
||||
private CollectionUtils() { |
||||
throw new UnsupportedOperationException("Construct CollectionUtils"); |
||||
} |
||||
|
||||
/** |
||||
* Removes certain attributes of each object in the list |
||||
* |
||||
* @param originList origin list |
||||
* @param exclusionSet exclusion set |
||||
* @param <T> T |
||||
* @return removes certain attributes of each object in the list |
||||
*/ |
||||
public static <T extends Object> List<Map<String, Object>> getListByExclusion(List<T> originList, |
||||
Set<String> exclusionSet) { |
||||
List<Map<String, Object>> instanceList = new ArrayList<>(); |
||||
if (originList == null) { |
||||
return instanceList; |
||||
} |
||||
Map<String, Object> instanceMap; |
||||
for (T instance : originList) { |
||||
BeanMap beanMap = new BeanMap(instance); |
||||
instanceMap = new LinkedHashMap<>(16, 0.75f, true); |
||||
for (Map.Entry<Object, Object> entry : beanMap.entrySet()) { |
||||
if (exclusionSet != null && exclusionSet.contains(entry.getKey())) { |
||||
continue; |
||||
} |
||||
instanceMap.put((String) entry.getKey(), entry.getValue()); |
||||
} |
||||
instanceList.add(instanceMap); |
||||
} |
||||
return instanceList; |
||||
} |
||||
|
||||
} |
@ -1,51 +0,0 @@
|
||||
/* |
||||
* 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.dolphinscheduler.common.utils; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Objects; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
@Slf4j |
||||
public class ConnectionUtils { |
||||
|
||||
private ConnectionUtils() { |
||||
throw new UnsupportedOperationException("Construct ConnectionUtils"); |
||||
} |
||||
|
||||
/** |
||||
* release resource |
||||
* |
||||
* @param resources resources |
||||
*/ |
||||
public static void releaseResource(AutoCloseable... resources) { |
||||
|
||||
if (resources == null || resources.length == 0) { |
||||
return; |
||||
} |
||||
Arrays.stream(resources).filter(Objects::nonNull) |
||||
.forEach(resource -> { |
||||
try { |
||||
resource.close(); |
||||
} catch (Exception e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
}); |
||||
} |
||||
} |
@ -1,112 +0,0 @@
|
||||
/* |
||||
* 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.dolphinscheduler.common.utils; |
||||
|
||||
import org.apache.dolphinscheduler.common.constants.Constants; |
||||
|
||||
import java.util.concurrent.Callable; |
||||
import java.util.concurrent.ExecutionException; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
import com.github.rholder.retry.RetryException; |
||||
import com.github.rholder.retry.Retryer; |
||||
import com.github.rholder.retry.RetryerBuilder; |
||||
import com.github.rholder.retry.StopStrategies; |
||||
import com.github.rholder.retry.WaitStrategies; |
||||
|
||||
public class RetryerUtils { |
||||
|
||||
private static Retryer<Boolean> defaultRetryerResultCheck; |
||||
private static Retryer<Boolean> defaultRetryerResultNoCheck; |
||||
|
||||
private RetryerUtils() { |
||||
throw new UnsupportedOperationException("Construct RetryerUtils"); |
||||
} |
||||
|
||||
private static Retryer<Boolean> getDefaultRetryerResultNoCheck() { |
||||
if (defaultRetryerResultNoCheck == null) { |
||||
defaultRetryerResultNoCheck = RetryerBuilder |
||||
.<Boolean>newBuilder() |
||||
.retryIfException() |
||||
.withWaitStrategy(WaitStrategies.fixedWait(Constants.SLEEP_TIME_MILLIS, TimeUnit.MILLISECONDS)) |
||||
.withStopStrategy(StopStrategies.stopAfterAttempt(3)) |
||||
.build(); |
||||
} |
||||
return defaultRetryerResultNoCheck; |
||||
} |
||||
|
||||
/** |
||||
* Gets default retryer. |
||||
* the retryer will retry 3 times if exceptions throw |
||||
* and wait 1 second between each retry |
||||
* |
||||
* @param checkResult true means the callable must return true before retrying |
||||
* false means that retry callable only throw exceptions |
||||
* @return the default retryer |
||||
*/ |
||||
public static Retryer<Boolean> getDefaultRetryer(boolean checkResult) { |
||||
return checkResult ? getDefaultRetryer() : getDefaultRetryerResultNoCheck(); |
||||
} |
||||
|
||||
/** |
||||
* Gets default retryer. |
||||
* the retryer will retry 3 times if exceptions throw |
||||
* and wait 1 second between each retry |
||||
* |
||||
* @return the default retryer |
||||
*/ |
||||
public static Retryer<Boolean> getDefaultRetryer() { |
||||
if (defaultRetryerResultCheck == null) { |
||||
defaultRetryerResultCheck = RetryerBuilder |
||||
.<Boolean>newBuilder() |
||||
.retryIfResult(Boolean.FALSE::equals) |
||||
.retryIfException() |
||||
.withWaitStrategy(WaitStrategies.fixedWait(Constants.SLEEP_TIME_MILLIS, TimeUnit.MILLISECONDS)) |
||||
.withStopStrategy(StopStrategies.stopAfterAttempt(3)) |
||||
.build(); |
||||
} |
||||
return defaultRetryerResultCheck; |
||||
} |
||||
|
||||
/** |
||||
* Use RETRYER to invoke the Callable |
||||
* |
||||
* @param callable the callable |
||||
* @param checkResult true means that retry callable before returning true |
||||
* false means that retry callable only throw exceptions |
||||
* @return the final result of callable |
||||
* @throws ExecutionException the execution exception |
||||
* @throws RetryException the retry exception |
||||
*/ |
||||
public static Boolean retryCall(final Callable<Boolean> callable, |
||||
boolean checkResult) throws ExecutionException, RetryException { |
||||
return getDefaultRetryer(checkResult).call(callable); |
||||
} |
||||
|
||||
/** |
||||
* Use RETRYER to invoke the Callable before returning true |
||||
* |
||||
* @param callable the callable |
||||
* @return the boolean |
||||
* @throws ExecutionException the execution exception |
||||
* @throws RetryException the retry exception |
||||
*/ |
||||
public static Boolean retryCall(final Callable<Boolean> callable) throws ExecutionException, RetryException { |
||||
return retryCall(callable, true); |
||||
} |
||||
} |
@ -1,28 +0,0 @@
|
||||
/* |
||||
* 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.dolphinscheduler.common.utils; |
||||
|
||||
/** |
||||
* tri function function interface
|
||||
*/ |
||||
@FunctionalInterface |
||||
public interface TriFunction<IN1, IN2, IN3, OUT1> { |
||||
|
||||
OUT1 apply(IN1 in1, IN2 in2, IN3 in3); |
||||
|
||||
} |
@ -1,218 +0,0 @@
|
||||
/* |
||||
* 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.dolphinscheduler.common.utils; |
||||
|
||||
import java.util.concurrent.ExecutionException; |
||||
|
||||
import org.junit.jupiter.api.Assertions; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import com.github.rholder.retry.RetryException; |
||||
import com.github.rholder.retry.Retryer; |
||||
|
||||
public class RetryerUtilsTest { |
||||
|
||||
@Test |
||||
public void testDefaultRetryer() { |
||||
Retryer<Boolean> retryer = RetryerUtils.getDefaultRetryer(); |
||||
Assertions.assertNotNull(retryer); |
||||
try { |
||||
boolean result = retryer.call(() -> true); |
||||
Assertions.assertTrue(result); |
||||
} catch (ExecutionException | RetryException e) { |
||||
Assertions.fail("Retry call failed " + e.getMessage()); |
||||
} |
||||
Retryer<Boolean> retryer1 = RetryerUtils.getDefaultRetryer(true); |
||||
Assertions.assertEquals(retryer, retryer1); |
||||
} |
||||
|
||||
@Test |
||||
public void testDefaultRetryerResultCheck() { |
||||
Retryer<Boolean> retryer = RetryerUtils.getDefaultRetryer(); |
||||
Assertions.assertNotNull(retryer); |
||||
try { |
||||
for (int execTarget = 1; execTarget <= 3; execTarget++) { |
||||
int finalExecTarget = execTarget; |
||||
int[] execTime = {0}; |
||||
boolean result = retryer.call(() -> { |
||||
execTime[0]++; |
||||
return execTime[0] == finalExecTarget; |
||||
}); |
||||
Assertions.assertEquals(finalExecTarget, execTime[0]); |
||||
Assertions.assertTrue(result); |
||||
} |
||||
} catch (ExecutionException | RetryException e) { |
||||
Assertions.fail("Retry call failed " + e.getMessage()); |
||||
} |
||||
int[] execTime = {0}; |
||||
try { |
||||
retryer.call(() -> { |
||||
execTime[0]++; |
||||
return execTime[0] == 4; |
||||
}); |
||||
Assertions.fail("Retry times not reached"); |
||||
} catch (RetryException e) { |
||||
Assertions.assertEquals(3, e.getNumberOfFailedAttempts()); |
||||
Assertions.assertEquals(3, execTime[0]); |
||||
} catch (ExecutionException e) { |
||||
Assertions.fail("Retry call failed " + e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testDefaultRetryerResultNoCheck() { |
||||
Retryer<Boolean> retryer = RetryerUtils.getDefaultRetryer(false); |
||||
Assertions.assertNotNull(retryer); |
||||
try { |
||||
for (int execTarget = 1; execTarget <= 5; execTarget++) { |
||||
int[] execTime = {0}; |
||||
boolean result = retryer.call(() -> { |
||||
execTime[0]++; |
||||
return execTime[0] > 1; |
||||
}); |
||||
Assertions.assertEquals(1, execTime[0]); |
||||
Assertions.assertFalse(result); |
||||
} |
||||
} catch (ExecutionException | RetryException e) { |
||||
Assertions.fail("Retry call failed " + e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testRecallResultCheck() { |
||||
try { |
||||
for (int execTarget = 1; execTarget <= 3; execTarget++) { |
||||
int finalExecTarget = execTarget; |
||||
int[] execTime = {0}; |
||||
boolean result = RetryerUtils.retryCall(() -> { |
||||
execTime[0]++; |
||||
return execTime[0] == finalExecTarget; |
||||
}); |
||||
Assertions.assertEquals(finalExecTarget, execTime[0]); |
||||
Assertions.assertTrue(result); |
||||
} |
||||
} catch (ExecutionException | RetryException e) { |
||||
Assertions.fail("Retry call failed " + e.getMessage()); |
||||
} |
||||
int[] execTime = {0}; |
||||
try { |
||||
RetryerUtils.retryCall(() -> { |
||||
execTime[0]++; |
||||
return execTime[0] == 4; |
||||
}); |
||||
Assertions.fail("Recall times not reached"); |
||||
} catch (RetryException e) { |
||||
Assertions.assertEquals(3, e.getNumberOfFailedAttempts()); |
||||
Assertions.assertEquals(3, execTime[0]); |
||||
} catch (ExecutionException e) { |
||||
Assertions.fail("Retry call failed " + e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testRecallResultCheckWithPara() { |
||||
try { |
||||
for (int execTarget = 1; execTarget <= 3; execTarget++) { |
||||
int finalExecTarget = execTarget; |
||||
int[] execTime = {0}; |
||||
boolean result = RetryerUtils.retryCall(() -> { |
||||
execTime[0]++; |
||||
return execTime[0] == finalExecTarget; |
||||
}, true); |
||||
Assertions.assertEquals(finalExecTarget, execTime[0]); |
||||
Assertions.assertTrue(result); |
||||
} |
||||
} catch (ExecutionException | RetryException e) { |
||||
Assertions.fail("Retry call failed " + e.getMessage()); |
||||
} |
||||
int[] execTime = {0}; |
||||
try { |
||||
RetryerUtils.retryCall(() -> { |
||||
execTime[0]++; |
||||
return execTime[0] == 4; |
||||
}, true); |
||||
Assertions.fail("Recall times not reached"); |
||||
} catch (RetryException e) { |
||||
Assertions.assertEquals(3, e.getNumberOfFailedAttempts()); |
||||
Assertions.assertEquals(3, execTime[0]); |
||||
} catch (ExecutionException e) { |
||||
Assertions.fail("Retry call failed " + e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testRecallResultNoCheck() { |
||||
try { |
||||
for (int execTarget = 1; execTarget <= 5; execTarget++) { |
||||
int[] execTime = {0}; |
||||
boolean result = RetryerUtils.retryCall(() -> { |
||||
execTime[0]++; |
||||
return execTime[0] > 1; |
||||
}, false); |
||||
Assertions.assertEquals(1, execTime[0]); |
||||
Assertions.assertFalse(result); |
||||
} |
||||
} catch (ExecutionException | RetryException e) { |
||||
Assertions.fail("Retry call failed " + e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
private void testRetryExceptionWithPara(boolean checkResult) { |
||||
try { |
||||
for (int execTarget = 1; execTarget <= 3; execTarget++) { |
||||
int finalExecTarget = execTarget; |
||||
int[] execTime = {0}; |
||||
boolean result = RetryerUtils.retryCall(() -> { |
||||
execTime[0]++; |
||||
if (execTime[0] != finalExecTarget) { |
||||
throw new IllegalArgumentException(String.valueOf(execTime[0])); |
||||
} |
||||
return true; |
||||
}, checkResult); |
||||
Assertions.assertEquals(finalExecTarget, execTime[0]); |
||||
Assertions.assertTrue(result); |
||||
} |
||||
} catch (ExecutionException | RetryException e) { |
||||
Assertions.fail("Retry call failed " + e.getMessage()); |
||||
} |
||||
int[] execTime = {0}; |
||||
try { |
||||
RetryerUtils.retryCall(() -> { |
||||
execTime[0]++; |
||||
if (execTime[0] != 4) { |
||||
throw new IllegalArgumentException(String.valueOf(execTime[0])); |
||||
} |
||||
return true; |
||||
}, checkResult); |
||||
Assertions.fail("Recall times not reached"); |
||||
} catch (RetryException e) { |
||||
Assertions.assertEquals(3, e.getNumberOfFailedAttempts()); |
||||
Assertions.assertEquals(3, execTime[0]); |
||||
Assertions.assertNotNull(e.getCause()); |
||||
Assertions.assertEquals(3, Integer.parseInt(e.getCause().getMessage())); |
||||
} catch (ExecutionException e) { |
||||
Assertions.fail("Retry call failed " + e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void testRetryException() { |
||||
testRetryExceptionWithPara(true); |
||||
testRetryExceptionWithPara(false); |
||||
} |
||||
} |
@ -1,54 +0,0 @@
|
||||
/* |
||||
* 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.dolphinscheduler.common.utils; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import org.junit.jupiter.api.Assertions; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
public class StringTest { |
||||
|
||||
@Test |
||||
public void stringCompareTest() { |
||||
|
||||
for (int j = 0; j < 5; j++) { |
||||
long start = System.currentTimeMillis(); |
||||
int size = 10000; |
||||
|
||||
List<String> taskList = new ArrayList<>(size); |
||||
|
||||
// init
|
||||
for (int i = 0; i < size; i++) { |
||||
taskList.add(String.format("%d_%010d_%010d", 1, i, i + 1)); |
||||
} |
||||
|
||||
String origin = taskList.get(0); |
||||
for (int i = 1; i < taskList.size(); i++) { |
||||
String str = taskList.get(i); |
||||
int result = str.compareTo(origin); |
||||
if (result < 0) { |
||||
origin = str; |
||||
} |
||||
} |
||||
double during = (System.currentTimeMillis() - start) / 1000.0; |
||||
Assertions.assertEquals("1_0000000000_0000000001", origin); |
||||
} |
||||
} |
||||
} |
@ -1,707 +0,0 @@
|
||||
/* |
||||
* 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.dolphinscheduler.service.utils; |
||||
|
||||
import org.apache.dolphinscheduler.common.constants.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.TaskDependType; |
||||
import org.apache.dolphinscheduler.common.graph.DAG; |
||||
import org.apache.dolphinscheduler.common.model.TaskNodeRelation; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
import org.apache.dolphinscheduler.plugin.task.api.enums.TaskExecutionStatus; |
||||
import org.apache.dolphinscheduler.plugin.task.api.model.Property; |
||||
import org.apache.dolphinscheduler.plugin.task.api.model.SwitchResultVo; |
||||
import org.apache.dolphinscheduler.plugin.task.api.parameters.ConditionsParameters; |
||||
import org.apache.dolphinscheduler.plugin.task.api.parameters.SwitchParameters; |
||||
import org.apache.dolphinscheduler.plugin.task.api.task.ConditionsLogicTaskChannelFactory; |
||||
import org.apache.dolphinscheduler.plugin.task.api.task.DependentLogicTaskChannelFactory; |
||||
import org.apache.dolphinscheduler.plugin.task.api.task.SwitchLogicTaskChannelFactory; |
||||
import org.apache.dolphinscheduler.service.model.TaskNode; |
||||
import org.apache.dolphinscheduler.service.process.WorkflowDag; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import lombok.Data; |
||||
import lombok.EqualsAndHashCode; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import org.junit.jupiter.api.Assertions; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException; |
||||
import com.google.common.collect.Lists; |
||||
import com.google.common.truth.Truth; |
||||
|
||||
public class DagHelperTest { |
||||
|
||||
@Test |
||||
public void testHaveSubAfterNode() { |
||||
Long parentNodeCode = 5293789969856L; |
||||
List<TaskNodeRelation> taskNodeRelations = new ArrayList<>(); |
||||
TaskNodeRelation relation = new TaskNodeRelation(); |
||||
relation.setStartNode(5293789969856L); |
||||
relation.setEndNode(5293789969857L); |
||||
taskNodeRelations.add(relation); |
||||
|
||||
TaskNodeRelation relationNext = new TaskNodeRelation(); |
||||
relationNext.setStartNode(5293789969856L); |
||||
relationNext.setEndNode(5293789969858L); |
||||
taskNodeRelations.add(relationNext); |
||||
|
||||
List<TaskNode> taskNodes = new ArrayList<>(); |
||||
TaskNode node = new TaskNode(); |
||||
node.setCode(5293789969856L); |
||||
node.setType("SHELL"); |
||||
|
||||
TaskNode subNode = new TaskNode(); |
||||
subNode.setCode(5293789969857L); |
||||
subNode.setType("BLOCKING"); |
||||
subNode.setPreTasks("[5293789969856]"); |
||||
|
||||
TaskNode subNextNode = new TaskNode(); |
||||
subNextNode.setCode(5293789969858L); |
||||
subNextNode.setType("CONDITIONS"); |
||||
subNextNode.setPreTasks("[5293789969856]"); |
||||
|
||||
taskNodes.add(node); |
||||
taskNodes.add(subNode); |
||||
taskNodes.add(subNextNode); |
||||
|
||||
WorkflowDag workflowDag = new WorkflowDag(); |
||||
workflowDag.setEdges(taskNodeRelations); |
||||
workflowDag.setNodes(taskNodes); |
||||
DAG<Long, TaskNode, TaskNodeRelation> dag = DagHelper.buildDagGraph(workflowDag); |
||||
boolean canSubmit = DagHelper.haveAllNodeAfterNode(parentNodeCode, dag); |
||||
Assertions.assertTrue(canSubmit); |
||||
|
||||
boolean haveConditions = DagHelper.haveConditionsAfterNode(parentNodeCode, dag); |
||||
Assertions.assertTrue(haveConditions); |
||||
|
||||
boolean dependent = DagHelper.haveSubAfterNode(parentNodeCode, dag, DependentLogicTaskChannelFactory.NAME); |
||||
Assertions.assertFalse(dependent); |
||||
} |
||||
|
||||
@Test |
||||
public void testTaskNodeCanSubmit() { |
||||
List<TaskNode> taskNodeList = new ArrayList<>(); |
||||
TaskNode node1 = new TaskNode(); |
||||
node1.setId("1"); |
||||
node1.setName("1"); |
||||
node1.setCode(1); |
||||
node1.setType("SHELL"); |
||||
taskNodeList.add(node1); |
||||
|
||||
TaskNode node2 = new TaskNode(); |
||||
node2.setId("2"); |
||||
node2.setName("2"); |
||||
node2.setCode(2); |
||||
node2.setType("SHELL"); |
||||
List<String> dep2 = new ArrayList<>(); |
||||
dep2.add("1"); |
||||
node2.setPreTasks(JSONUtils.toJsonString(dep2)); |
||||
taskNodeList.add(node2); |
||||
|
||||
TaskNode node4 = new TaskNode(); |
||||
node4.setId("4"); |
||||
node4.setName("4"); |
||||
node4.setCode(4); |
||||
node4.setType("SHELL"); |
||||
taskNodeList.add(node4); |
||||
|
||||
TaskNode node3 = new TaskNode(); |
||||
node3.setId("3"); |
||||
node3.setName("3"); |
||||
node3.setCode(3); |
||||
node3.setType("SHELL"); |
||||
List<String> dep3 = new ArrayList<>(); |
||||
dep3.add("2"); |
||||
dep3.add("4"); |
||||
node3.setPreTasks(JSONUtils.toJsonString(dep3)); |
||||
taskNodeList.add(node3); |
||||
|
||||
TaskNode node5 = new TaskNode(); |
||||
node5.setId("5"); |
||||
node5.setName("5"); |
||||
node5.setCode(5); |
||||
node5.setType("SHELL"); |
||||
List<String> dep5 = new ArrayList<>(); |
||||
dep5.add("3"); |
||||
dep5.add("8"); |
||||
node5.setPreTasks(JSONUtils.toJsonString(dep5)); |
||||
taskNodeList.add(node5); |
||||
|
||||
TaskNode node6 = new TaskNode(); |
||||
node6.setId("6"); |
||||
node6.setName("6"); |
||||
node6.setCode(6); |
||||
node6.setType("SHELL"); |
||||
List<String> dep6 = new ArrayList<>(); |
||||
dep6.add("3"); |
||||
node6.setPreTasks(JSONUtils.toJsonString(dep6)); |
||||
taskNodeList.add(node6); |
||||
|
||||
TaskNode node7 = new TaskNode(); |
||||
node7.setId("7"); |
||||
node7.setName("7"); |
||||
node7.setCode(7); |
||||
node7.setType("SHELL"); |
||||
List<String> dep7 = new ArrayList<>(); |
||||
dep7.add("5"); |
||||
node7.setPreTasks(JSONUtils.toJsonString(dep7)); |
||||
taskNodeList.add(node7); |
||||
|
||||
TaskNode node8 = new TaskNode(); |
||||
node8.setId("8"); |
||||
node8.setName("8"); |
||||
node8.setCode(8); |
||||
node8.setType("SHELL"); |
||||
List<String> dep8 = new ArrayList<>(); |
||||
dep8.add("2"); |
||||
node8.setPreTasks(JSONUtils.toJsonString(dep8)); |
||||
taskNodeList.add(node8); |
||||
|
||||
List<Long> startNodes = new ArrayList<>(); |
||||
List<Long> recoveryNodes = new ArrayList<>(); |
||||
List<TaskNode> destTaskNodeList = DagHelper.generateFlowNodeListByStartNode(taskNodeList, |
||||
startNodes, recoveryNodes, TaskDependType.TASK_POST); |
||||
List<TaskNodeRelation> taskNodeRelations = DagHelper.generateRelationListByFlowNodes(destTaskNodeList); |
||||
WorkflowDag workflowDag = new WorkflowDag(); |
||||
workflowDag.setEdges(taskNodeRelations); |
||||
workflowDag.setNodes(destTaskNodeList); |
||||
|
||||
// 1->2->3->5->7
|
||||
// 4->3->6
|
||||
// 1->2->8->5->7
|
||||
DAG<Long, TaskNode, TaskNodeRelation> dag = DagHelper.buildDagGraph(workflowDag); |
||||
TaskNode taskNode3 = dag.getNode(3L); |
||||
Map<Long, TaskInstance> completeTaskList = new HashMap<>(); |
||||
Map<Long, TaskNode> skipNodeList = new HashMap<>(); |
||||
completeTaskList.putIfAbsent(1L, new TaskInstance()); |
||||
Boolean canSubmit = false; |
||||
|
||||
// 2/4 are forbidden submit 3
|
||||
node2 = dag.getNode(2L); |
||||
node2.setRunFlag(Constants.FLOWNODE_RUN_FLAG_FORBIDDEN); |
||||
TaskNode nodex = dag.getNode(4L); |
||||
nodex.setRunFlag(Constants.FLOWNODE_RUN_FLAG_FORBIDDEN); |
||||
canSubmit = DagHelper.allDependsForbiddenOrEnd(taskNode3, dag, skipNodeList, completeTaskList); |
||||
Assertions.assertEquals(canSubmit, true); |
||||
|
||||
// 2forbidden, 3 cannot be submit
|
||||
completeTaskList.putIfAbsent(2L, new TaskInstance()); |
||||
TaskNode nodey = dag.getNode(4L); |
||||
nodey.setRunFlag(""); |
||||
canSubmit = DagHelper.allDependsForbiddenOrEnd(taskNode3, dag, skipNodeList, completeTaskList); |
||||
Assertions.assertEquals(canSubmit, false); |
||||
|
||||
// 2/3 forbidden submit 5
|
||||
node3 = dag.getNode(3L); |
||||
node3.setRunFlag(Constants.FLOWNODE_RUN_FLAG_FORBIDDEN); |
||||
node8 = dag.getNode(8L); |
||||
node8.setRunFlag(Constants.FLOWNODE_RUN_FLAG_FORBIDDEN); |
||||
node5 = dag.getNode(5L); |
||||
canSubmit = DagHelper.allDependsForbiddenOrEnd(node5, dag, skipNodeList, completeTaskList); |
||||
Assertions.assertEquals(canSubmit, true); |
||||
} |
||||
|
||||
@Test |
||||
public void testParsePostNodeList() { |
||||
List<TaskNode> taskNodeList = new ArrayList<>(); |
||||
TaskNode node1 = new TaskNode(); |
||||
node1.setId("1"); |
||||
node1.setName("1"); |
||||
node1.setCode(1); |
||||
node1.setType("SHELL"); |
||||
taskNodeList.add(node1); |
||||
|
||||
TaskNode node2 = new TaskNode(); |
||||
node2.setId("2"); |
||||
node2.setName("2"); |
||||
node2.setCode(2); |
||||
node2.setType("SHELL"); |
||||
List<String> dep2 = new ArrayList<>(); |
||||
dep2.add("1"); |
||||
node2.setPreTasks(JSONUtils.toJsonString(dep2)); |
||||
taskNodeList.add(node2); |
||||
|
||||
TaskNode node4 = new TaskNode(); |
||||
node4.setId("4"); |
||||
node4.setName("4"); |
||||
node4.setCode(4); |
||||
node4.setType("SHELL"); |
||||
taskNodeList.add(node4); |
||||
|
||||
TaskNode node3 = new TaskNode(); |
||||
node3.setId("3"); |
||||
node3.setName("3"); |
||||
node3.setCode(3); |
||||
node3.setType("SHELL"); |
||||
List<String> dep3 = new ArrayList<>(); |
||||
dep3.add("2"); |
||||
dep3.add("4"); |
||||
node3.setPreTasks(JSONUtils.toJsonString(dep3)); |
||||
taskNodeList.add(node3); |
||||
|
||||
TaskNode node5 = new TaskNode(); |
||||
node5.setId("5"); |
||||
node5.setName("5"); |
||||
node5.setCode(5); |
||||
node5.setType("SHELL"); |
||||
List<String> dep5 = new ArrayList<>(); |
||||
dep5.add("3"); |
||||
dep5.add("8"); |
||||
node5.setPreTasks(JSONUtils.toJsonString(dep5)); |
||||
taskNodeList.add(node5); |
||||
|
||||
TaskNode node6 = new TaskNode(); |
||||
node6.setId("6"); |
||||
node6.setName("6"); |
||||
node6.setCode(6); |
||||
node6.setType("SHELL"); |
||||
List<String> dep6 = new ArrayList<>(); |
||||
dep6.add("3"); |
||||
node6.setPreTasks(JSONUtils.toJsonString(dep6)); |
||||
taskNodeList.add(node6); |
||||
|
||||
TaskNode node7 = new TaskNode(); |
||||
node7.setId("7"); |
||||
node7.setName("7"); |
||||
node7.setCode(7); |
||||
node7.setType("SHELL"); |
||||
List<String> dep7 = new ArrayList<>(); |
||||
dep7.add("5"); |
||||
node7.setPreTasks(JSONUtils.toJsonString(dep7)); |
||||
taskNodeList.add(node7); |
||||
|
||||
TaskNode node8 = new TaskNode(); |
||||
node8.setId("8"); |
||||
node8.setName("8"); |
||||
node8.setCode(8); |
||||
node8.setType("SHELL"); |
||||
List<String> dep8 = new ArrayList<>(); |
||||
dep8.add("2"); |
||||
node8.setPreTasks(JSONUtils.toJsonString(dep8)); |
||||
taskNodeList.add(node8); |
||||
|
||||
List<Long> startNodes = new ArrayList<>(); |
||||
List<Long> recoveryNodes = new ArrayList<>(); |
||||
List<TaskNode> destTaskNodeList = DagHelper.generateFlowNodeListByStartNode(taskNodeList, |
||||
startNodes, recoveryNodes, TaskDependType.TASK_POST); |
||||
List<TaskNodeRelation> taskNodeRelations = DagHelper.generateRelationListByFlowNodes(destTaskNodeList); |
||||
WorkflowDag workflowDag = new WorkflowDag(); |
||||
workflowDag.setEdges(taskNodeRelations); |
||||
workflowDag.setNodes(destTaskNodeList); |
||||
|
||||
// 1->2->3->5->7
|
||||
// 4->3->6
|
||||
// 1->2->8->5->7
|
||||
DAG<Long, TaskNode, TaskNodeRelation> dag = DagHelper.buildDagGraph(workflowDag); |
||||
Map<Long, TaskInstance> completeTaskList = new HashMap<>(); |
||||
Map<Long, TaskNode> skipNodeList = new HashMap<>(); |
||||
|
||||
Set<Long> postNodes = null; |
||||
// complete : null
|
||||
// expect post: 1/4
|
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertEquals(2, postNodes.size()); |
||||
Assertions.assertTrue(postNodes.contains(1L)); |
||||
Assertions.assertTrue(postNodes.contains(4L)); |
||||
|
||||
// complete : 1
|
||||
// expect post: 2/4
|
||||
completeTaskList.put(1L, new TaskInstance()); |
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertEquals(2, postNodes.size()); |
||||
Assertions.assertTrue(postNodes.contains(2L)); |
||||
Assertions.assertTrue(postNodes.contains(4L)); |
||||
|
||||
// complete : 1/2
|
||||
// expect post: 4
|
||||
completeTaskList.put(2L, new TaskInstance()); |
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertEquals(2, postNodes.size()); |
||||
Assertions.assertTrue(postNodes.contains(4L)); |
||||
Assertions.assertTrue(postNodes.contains(8L)); |
||||
|
||||
// complete : 1/2/4
|
||||
// expect post: 3
|
||||
completeTaskList.put(4L, new TaskInstance()); |
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertEquals(2, postNodes.size()); |
||||
Assertions.assertTrue(postNodes.contains(3L)); |
||||
Assertions.assertTrue(postNodes.contains(8L)); |
||||
|
||||
// complete : 1/2/4/3
|
||||
// expect post: 8/6
|
||||
completeTaskList.put(3L, new TaskInstance()); |
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertEquals(2, postNodes.size()); |
||||
Assertions.assertTrue(postNodes.contains(8L)); |
||||
Assertions.assertTrue(postNodes.contains(6L)); |
||||
|
||||
// complete : 1/2/4/3/8
|
||||
// expect post: 6/5
|
||||
completeTaskList.put(8L, new TaskInstance()); |
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertEquals(2, postNodes.size()); |
||||
Assertions.assertTrue(postNodes.contains(5L)); |
||||
Assertions.assertTrue(postNodes.contains(6L)); |
||||
// complete : 1/2/4/3/5/6/8
|
||||
// expect post: 7
|
||||
completeTaskList.put(6L, new TaskInstance()); |
||||
completeTaskList.put(5L, new TaskInstance()); |
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertEquals(1, postNodes.size()); |
||||
Assertions.assertTrue(postNodes.contains(7L)); |
||||
} |
||||
|
||||
@Test |
||||
public void testForbiddenPostNode() throws IOException { |
||||
DAG<Long, TaskNode, TaskNodeRelation> dag = generateDag(); |
||||
Map<Long, TaskInstance> completeTaskList = new HashMap<>(); |
||||
Map<Long, TaskNode> skipNodeList = new HashMap<>(); |
||||
Set<Long> postNodes = null; |
||||
// dag: 1-2-3-5-7 4-3-6 2-8-5-7
|
||||
// forbid:2 complete:1 post:4/8
|
||||
completeTaskList.put(1L, new TaskInstance()); |
||||
TaskNode node2 = dag.getNode(2L); |
||||
node2.setRunFlag(Constants.FLOWNODE_RUN_FLAG_FORBIDDEN); |
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertEquals(2, postNodes.size()); |
||||
Assertions.assertTrue(postNodes.contains(4L)); |
||||
Assertions.assertTrue(postNodes.contains(8L)); |
||||
|
||||
// forbid:2/4 complete:1 post:3/8
|
||||
TaskNode node4 = dag.getNode(4L); |
||||
node4.setRunFlag(Constants.FLOWNODE_RUN_FLAG_FORBIDDEN); |
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertEquals(2, postNodes.size()); |
||||
Assertions.assertTrue(postNodes.contains(3L)); |
||||
Assertions.assertTrue(postNodes.contains(8L)); |
||||
|
||||
// forbid:2/4/5 complete:1/8 post:3
|
||||
completeTaskList.put(8L, new TaskInstance()); |
||||
TaskNode node5 = dag.getNode(5L); |
||||
node5.setRunFlag(Constants.FLOWNODE_RUN_FLAG_FORBIDDEN); |
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertEquals(1, postNodes.size()); |
||||
Assertions.assertTrue(postNodes.contains(3L)); |
||||
} |
||||
|
||||
@Test |
||||
public void testConditionPostNode() throws IOException { |
||||
DAG<Long, TaskNode, TaskNodeRelation> dag = generateDag(); |
||||
Map<Long, TaskInstance> completeTaskList = new HashMap<>(); |
||||
Map<Long, TaskNode> skipNodeList = new HashMap<>(); |
||||
Set<Long> postNodes = null; |
||||
// dag: 1-2-3-5-7 4-3-6 2-8-5-7
|
||||
// 3-if
|
||||
completeTaskList.put(1L, new TaskInstance()); |
||||
completeTaskList.put(2L, new TaskInstance()); |
||||
completeTaskList.put(4L, new TaskInstance()); |
||||
|
||||
TaskInstance taskInstance3 = new TaskInstance(); |
||||
taskInstance3.setTaskType(ConditionsLogicTaskChannelFactory.NAME); |
||||
ConditionsParameters.ConditionResult conditionResult = ConditionsParameters.ConditionResult.builder() |
||||
.conditionSuccess(true) |
||||
.successNode(Lists.newArrayList(5L)) |
||||
.failedNode(Lists.newArrayList(6L)) |
||||
.build(); |
||||
ConditionsParameters conditionsParameters = new ConditionsParameters(); |
||||
conditionsParameters.setConditionResult(conditionResult); |
||||
taskInstance3.setTaskParams(JSONUtils.toJsonString(conditionsParameters)); |
||||
taskInstance3.setState(TaskExecutionStatus.SUCCESS); |
||||
TaskNode node3 = dag.getNode(3L); |
||||
node3.setType(ConditionsLogicTaskChannelFactory.NAME); |
||||
// complete 1/2/3/4 expect:8
|
||||
completeTaskList.put(3L, taskInstance3); |
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertEquals(1, postNodes.size()); |
||||
Assertions.assertTrue(postNodes.contains(8L)); |
||||
|
||||
// 2.complete 1/2/3/4/8 expect:5 skip:6
|
||||
completeTaskList.put(8L, new TaskInstance()); |
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertTrue(postNodes.contains(5L)); |
||||
Assertions.assertEquals(1, skipNodeList.size()); |
||||
Assertions.assertTrue(skipNodeList.containsKey(6L)); |
||||
|
||||
// 3.complete 1/2/3/4/5/8 expect post:7 skip:6
|
||||
skipNodeList.clear(); |
||||
TaskInstance taskInstance1 = new TaskInstance(); |
||||
completeTaskList.put(5L, taskInstance1); |
||||
postNodes = DagHelper.parsePostNodes(null, skipNodeList, dag, completeTaskList); |
||||
Assertions.assertEquals(1, postNodes.size()); |
||||
Assertions.assertTrue(postNodes.contains(7L)); |
||||
Assertions.assertEquals(1, skipNodeList.size()); |
||||
Assertions.assertTrue(skipNodeList.containsKey(6L)); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void testSwitchPostNode() { |
||||
List<TaskNode> taskNodeList = new ArrayList<>(); |
||||
|
||||
TaskNode node = new TaskNode(); |
||||
node.setId("0"); |
||||
node.setName("0"); |
||||
node.setCode(0); |
||||
node.setType("SHELL"); |
||||
taskNodeList.add(node); |
||||
|
||||
TaskNode node1 = new TaskNode(); |
||||
node1.setId("1"); |
||||
node1.setName("1"); |
||||
node1.setCode(1); |
||||
node1.setType(SwitchLogicTaskChannelFactory.NAME); |
||||
SwitchParameters switchParameters = new SwitchParameters(); |
||||
node1.setParams(JSONUtils.toJsonString(switchParameters)); |
||||
taskNodeList.add(node1); |
||||
|
||||
TaskNode node2 = new TaskNode(); |
||||
node2.setId("2"); |
||||
node2.setName("2"); |
||||
node2.setCode(2); |
||||
node2.setType("SHELL"); |
||||
List<String> dep2 = new ArrayList<>(); |
||||
dep2.add("1"); |
||||
node2.setPreTasks(JSONUtils.toJsonString(dep2)); |
||||
taskNodeList.add(node2); |
||||
|
||||
TaskNode node4 = new TaskNode(); |
||||
node4.setId("4"); |
||||
node4.setName("4"); |
||||
node4.setCode(4); |
||||
node4.setType("SHELL"); |
||||
List<String> dep4 = new ArrayList<>(); |
||||
dep4.add("1"); |
||||
node4.setPreTasks(JSONUtils.toJsonString(dep4)); |
||||
taskNodeList.add(node4); |
||||
|
||||
TaskNode node5 = new TaskNode(); |
||||
node5.setId("5"); |
||||
node5.setName("5"); |
||||
node5.setCode(5); |
||||
node5.setType("SHELL"); |
||||
List<Long> dep5 = new ArrayList<>(); |
||||
dep5.add(1L); |
||||
node5.setPreTasks(JSONUtils.toJsonString(dep5)); |
||||
taskNodeList.add(node5); |
||||
|
||||
TaskNode node6 = new TaskNode(); |
||||
node5.setId("6"); |
||||
node5.setName("6"); |
||||
node5.setCode(6); |
||||
node5.setType("SHELL"); |
||||
List<Long> dep6 = new ArrayList<>(); |
||||
dep5.add(2L); |
||||
dep5.add(4L); |
||||
node5.setPreTasks(JSONUtils.toJsonString(dep6)); |
||||
taskNodeList.add(node6); |
||||
|
||||
List<Long> startNodes = new ArrayList<>(); |
||||
List<Long> recoveryNodes = new ArrayList<>(); |
||||
|
||||
// 0
|
||||
// 1->2->6
|
||||
// 1->4->6
|
||||
// 1->5
|
||||
List<TaskNode> destTaskNodeList = DagHelper.generateFlowNodeListByStartNode(taskNodeList, |
||||
startNodes, recoveryNodes, TaskDependType.TASK_POST); |
||||
List<TaskNodeRelation> taskNodeRelations = DagHelper.generateRelationListByFlowNodes(destTaskNodeList); |
||||
WorkflowDag workflowDag = new WorkflowDag(); |
||||
workflowDag.setEdges(taskNodeRelations); |
||||
workflowDag.setNodes(destTaskNodeList); |
||||
|
||||
DAG<Long, TaskNode, TaskNodeRelation> dag = DagHelper.buildDagGraph(workflowDag); |
||||
Map<Long, TaskNode> skipTaskNodeList = new HashMap<>(); |
||||
Map<Long, TaskInstance> completeTaskList = new HashMap<>(); |
||||
completeTaskList.put(0L, new TaskInstance()); |
||||
TaskInstance taskInstance = new TaskInstance(); |
||||
taskInstance.setState(TaskExecutionStatus.SUCCESS); |
||||
taskInstance.setTaskCode(1L); |
||||
taskInstance.setTaskType(SwitchLogicTaskChannelFactory.NAME); |
||||
switchParameters = SwitchParameters.builder() |
||||
.nextBranch(5L) |
||||
.switchResult(SwitchParameters.SwitchResult.builder() |
||||
.dependTaskList(Lists.newArrayList( |
||||
new SwitchResultVo("", 2L), |
||||
new SwitchResultVo("", 4L))) |
||||
.nextNode(5L) |
||||
.build()) |
||||
.build(); |
||||
taskInstance.setTaskParams(JSONUtils.toJsonString(switchParameters)); |
||||
completeTaskList.put(1l, taskInstance); |
||||
List<Long> nextBranch = DagHelper.skipTaskNode4Switch(skipTaskNodeList, taskInstance, dag); |
||||
Assertions.assertNotNull(skipTaskNodeList.get(2L)); |
||||
Assertions.assertNotNull(skipTaskNodeList.get(4L)); |
||||
Assertions.assertEquals(2, skipTaskNodeList.size()); |
||||
Truth.assertThat(nextBranch).containsExactly(5L); |
||||
} |
||||
|
||||
/** |
||||
* process: |
||||
* 1->2->3->5->7 |
||||
* 4->3->6 |
||||
* 1->2->8->5->7 |
||||
* DAG graph: |
||||
* 4 -> -> 6 |
||||
* \ / |
||||
* 1 -> 2 -> 3 -> 5 -> 7 |
||||
* \ / |
||||
* -> 8 -> |
||||
* |
||||
* @return dag |
||||
* @throws JsonProcessingException if error throws JsonProcessingException |
||||
*/ |
||||
private DAG<Long, TaskNode, TaskNodeRelation> generateDag() throws IOException { |
||||
List<TaskNode> taskNodeList = new ArrayList<>(); |
||||
TaskNode node1 = new TaskNode(); |
||||
node1.setId("1"); |
||||
node1.setName("1"); |
||||
node1.setCode(1); |
||||
node1.setType("SHELL"); |
||||
taskNodeList.add(node1); |
||||
|
||||
TaskNode node2 = new TaskNode(); |
||||
node2.setId("2"); |
||||
node2.setName("2"); |
||||
node2.setCode(2); |
||||
node2.setType("SHELL"); |
||||
List<String> dep2 = new ArrayList<>(); |
||||
dep2.add("1"); |
||||
node2.setPreTasks(JSONUtils.toJsonString(dep2)); |
||||
taskNodeList.add(node2); |
||||
|
||||
TaskNode node4 = new TaskNode(); |
||||
node4.setId("4"); |
||||
node4.setName("4"); |
||||
node4.setCode(4); |
||||
node4.setType("SHELL"); |
||||
taskNodeList.add(node4); |
||||
|
||||
TaskNode node3 = new TaskNode(); |
||||
node3.setId("3"); |
||||
node3.setName("3"); |
||||
node3.setCode(3); |
||||
node3.setType("SHELL"); |
||||
List<String> dep3 = new ArrayList<>(); |
||||
dep3.add("2"); |
||||
dep3.add("4"); |
||||
node3.setPreTasks(JSONUtils.toJsonString(dep3)); |
||||
taskNodeList.add(node3); |
||||
|
||||
TaskNode node5 = new TaskNode(); |
||||
node5.setId("5"); |
||||
node5.setName("5"); |
||||
node5.setCode(5); |
||||
node5.setType("SHELL"); |
||||
List<String> dep5 = new ArrayList<>(); |
||||
dep5.add("3"); |
||||
dep5.add("8"); |
||||
node5.setPreTasks(JSONUtils.toJsonString(dep5)); |
||||
taskNodeList.add(node5); |
||||
|
||||
TaskNode node6 = new TaskNode(); |
||||
node6.setId("6"); |
||||
node6.setName("6"); |
||||
node6.setCode(6); |
||||
node6.setType("SHELL"); |
||||
List<String> dep6 = new ArrayList<>(); |
||||
dep6.add("3"); |
||||
node6.setPreTasks(JSONUtils.toJsonString(dep6)); |
||||
taskNodeList.add(node6); |
||||
|
||||
TaskNode node7 = new TaskNode(); |
||||
node7.setId("7"); |
||||
node7.setName("7"); |
||||
node7.setCode(7); |
||||
node7.setType("SHELL"); |
||||
List<String> dep7 = new ArrayList<>(); |
||||
dep7.add("5"); |
||||
node7.setPreTasks(JSONUtils.toJsonString(dep7)); |
||||
taskNodeList.add(node7); |
||||
|
||||
TaskNode node8 = new TaskNode(); |
||||
node8.setId("8"); |
||||
node8.setName("8"); |
||||
node8.setCode(8); |
||||
node8.setType("SHELL"); |
||||
List<String> dep8 = new ArrayList<>(); |
||||
dep8.add("2"); |
||||
node8.setPreTasks(JSONUtils.toJsonString(dep8)); |
||||
taskNodeList.add(node8); |
||||
|
||||
List<Long> startNodes = new ArrayList<>(); |
||||
List<Long> recoveryNodes = new ArrayList<>(); |
||||
List<TaskNode> destTaskNodeList = DagHelper.generateFlowNodeListByStartNode(taskNodeList, |
||||
startNodes, recoveryNodes, TaskDependType.TASK_POST); |
||||
List<TaskNodeRelation> taskNodeRelations = DagHelper.generateRelationListByFlowNodes(destTaskNodeList); |
||||
WorkflowDag workflowDag = new WorkflowDag(); |
||||
workflowDag.setEdges(taskNodeRelations); |
||||
workflowDag.setNodes(destTaskNodeList); |
||||
return DagHelper.buildDagGraph(workflowDag); |
||||
} |
||||
|
||||
@Test |
||||
public void testBuildDagGraph() { |
||||
String shellJson = |
||||
"{\"globalParams\":[],\"tasks\":[{\"type\":\"SHELL\",\"id\":\"tasks-9527\",\"name\":\"shell-1\"," |
||||
+ |
||||
"\"params\":{\"resourceList\":[],\"localParams\":[],\"rawScript\":\"#!/bin/bash\\necho \\\"shell-1\\\"\"}," |
||||
+ |
||||
"\"description\":\"\",\"runFlag\":\"NORMAL\",\"dependence\":{},\"maxRetryTimes\":\"0\",\"retryInterval\":\"1\"," |
||||
+ |
||||
"\"timeout\":{\"strategy\":\"\",\"interval\":1,\"enable\":false},\"taskInstancePriority\":\"MEDIUM\"," |
||||
+ |
||||
"\"workerGroupId\":-1,\"preTasks\":[]}],\"tenantId\":1,\"timeout\":0}"; |
||||
|
||||
ProcessData processData = JSONUtils.parseObject(shellJson, ProcessData.class); |
||||
assert processData != null; |
||||
List<TaskNode> taskNodeList = processData.getTasks(); |
||||
WorkflowDag workflowDag = DagHelper.getWorkflowDag(taskNodeList); |
||||
DAG<Long, TaskNode, TaskNodeRelation> dag = DagHelper.buildDagGraph(workflowDag); |
||||
Assertions.assertNotNull(dag); |
||||
} |
||||
|
||||
@Data |
||||
@NoArgsConstructor |
||||
private static class ProcessData { |
||||
|
||||
@EqualsAndHashCode.Include |
||||
private List<TaskNode> tasks; |
||||
|
||||
@EqualsAndHashCode.Include |
||||
private List<Property> globalParams; |
||||
|
||||
private int timeout; |
||||
|
||||
private int tenantId; |
||||
|
||||
public ProcessData(List<TaskNode> tasks, List<Property> globalParams) { |
||||
this.tasks = tasks; |
||||
this.globalParams = globalParams; |
||||
} |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue