Yann Ann
2 years ago
committed by
GitHub
14 changed files with 788 additions and 475 deletions
@ -0,0 +1,88 @@
|
||||
/* |
||||
* 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.command; |
||||
|
||||
import org.apache.dolphinscheduler.dao.entity.Command; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstanceMap; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Command Service |
||||
*/ |
||||
public interface CommandService { |
||||
|
||||
/** |
||||
* Save error command, and delete original command. If the given command has already been moved into error command, |
||||
* will throw {@link java.sql.SQLIntegrityConstraintViolationException ). |
||||
* @param command command |
||||
* @param message message |
||||
*/ |
||||
void moveToErrorCommand(Command command, String message); |
||||
|
||||
/** |
||||
* Create new command |
||||
* @param command command |
||||
* @return result |
||||
*/ |
||||
int createCommand(Command command); |
||||
|
||||
/** |
||||
* Get command page |
||||
* @param pageSize page size |
||||
* @param pageNumber page number |
||||
* @param masterCount master count |
||||
* @param thisMasterSlot master slot |
||||
* @return command page |
||||
*/ |
||||
List<Command> findCommandPageBySlot(int pageSize, int pageNumber, int masterCount, int thisMasterSlot); |
||||
|
||||
/** |
||||
* check the input command exists in queue list |
||||
* |
||||
* @param command command |
||||
* @return create command result |
||||
*/ |
||||
boolean verifyIsNeedCreateCommand(Command command); |
||||
|
||||
/** |
||||
* create recovery waiting thread command when thread pool is not enough for the process instance. |
||||
* sub work process instance need not create recovery command. |
||||
* create recovery waiting thread command and delete origin command at the same time. |
||||
* if the recovery command is exists, only update the field update_time |
||||
* |
||||
* @param originCommand originCommand |
||||
* @param processInstance processInstance |
||||
*/ |
||||
void createRecoveryWaitingThreadCommand(Command originCommand, ProcessInstance processInstance); |
||||
|
||||
/** |
||||
* create sub work process command |
||||
* @param parentProcessInstance parent process instance |
||||
* @param childInstance child process instance |
||||
* @param instanceMap process instance map |
||||
* @param task task instance |
||||
* @return command |
||||
*/ |
||||
Command createSubProcessCommand(ProcessInstance parentProcessInstance, |
||||
ProcessInstance childInstance, |
||||
ProcessInstanceMap instanceMap, |
||||
TaskInstance task); |
||||
} |
@ -0,0 +1,272 @@
|
||||
/* |
||||
* 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.command; |
||||
|
||||
import static org.apache.dolphinscheduler.common.Constants.CMD_PARAM_RECOVER_PROCESS_ID_STRING; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.CommandType; |
||||
import org.apache.dolphinscheduler.common.enums.Flag; |
||||
import org.apache.dolphinscheduler.common.enums.TaskDependType; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.Command; |
||||
import org.apache.dolphinscheduler.dao.entity.ErrorCommand; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstanceMap; |
||||
import org.apache.dolphinscheduler.dao.entity.Schedule; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
import org.apache.dolphinscheduler.dao.mapper.CommandMapper; |
||||
import org.apache.dolphinscheduler.dao.mapper.ErrorCommandMapper; |
||||
import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionMapper; |
||||
import org.apache.dolphinscheduler.dao.mapper.ScheduleMapper; |
||||
import org.apache.dolphinscheduler.plugin.task.api.enums.Direct; |
||||
import org.apache.dolphinscheduler.plugin.task.api.model.Property; |
||||
import org.apache.dolphinscheduler.service.utils.ParamUtils; |
||||
|
||||
import org.apache.commons.collections.CollectionUtils; |
||||
import org.apache.commons.lang3.StringUtils; |
||||
|
||||
import java.util.Date; |
||||
import java.util.EnumMap; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode; |
||||
import com.google.common.collect.Lists; |
||||
import io.micrometer.core.annotation.Counted; |
||||
|
||||
/** |
||||
* Command Service implementation |
||||
*/ |
||||
@Component |
||||
public class CommandServiceImpl implements CommandService { |
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CommandServiceImpl.class); |
||||
|
||||
@Autowired |
||||
private ErrorCommandMapper errorCommandMapper; |
||||
|
||||
@Autowired |
||||
private CommandMapper commandMapper; |
||||
|
||||
@Autowired |
||||
private ScheduleMapper scheduleMapper; |
||||
|
||||
@Autowired |
||||
private ProcessDefinitionMapper processDefineMapper; |
||||
|
||||
@Override |
||||
public void moveToErrorCommand(Command command, String message) { |
||||
ErrorCommand errorCommand = new ErrorCommand(command, message); |
||||
this.errorCommandMapper.insert(errorCommand); |
||||
this.commandMapper.deleteById(command.getId()); |
||||
} |
||||
|
||||
@Override |
||||
@Counted("ds.workflow.create.command.count") |
||||
public int createCommand(Command command) { |
||||
int result = 0; |
||||
if (command == null) { |
||||
return result; |
||||
} |
||||
// add command timezone
|
||||
Schedule schedule = scheduleMapper.queryByProcessDefinitionCode(command.getProcessDefinitionCode()); |
||||
if (schedule != null) { |
||||
Map<String, String> commandParams = |
||||
StringUtils.isNotBlank(command.getCommandParam()) ? JSONUtils.toMap(command.getCommandParam()) |
||||
: new HashMap<>(); |
||||
commandParams.put(Constants.SCHEDULE_TIMEZONE, schedule.getTimezoneId()); |
||||
command.setCommandParam(JSONUtils.toJsonString(commandParams)); |
||||
} |
||||
command.setId(null); |
||||
result = commandMapper.insert(command); |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public List<Command> findCommandPageBySlot(int pageSize, int pageNumber, int masterCount, int thisMasterSlot) { |
||||
if (masterCount <= 0) { |
||||
return Lists.newArrayList(); |
||||
} |
||||
return commandMapper.queryCommandPageBySlot(pageSize, pageNumber * pageSize, masterCount, thisMasterSlot); |
||||
} |
||||
|
||||
@Override |
||||
public boolean verifyIsNeedCreateCommand(Command command) { |
||||
boolean isNeedCreate = true; |
||||
EnumMap<CommandType, Integer> cmdTypeMap = new EnumMap<>(CommandType.class); |
||||
cmdTypeMap.put(CommandType.REPEAT_RUNNING, 1); |
||||
cmdTypeMap.put(CommandType.RECOVER_SUSPENDED_PROCESS, 1); |
||||
cmdTypeMap.put(CommandType.START_FAILURE_TASK_PROCESS, 1); |
||||
CommandType commandType = command.getCommandType(); |
||||
|
||||
if (!cmdTypeMap.containsKey(commandType)) { |
||||
return true; |
||||
} |
||||
|
||||
ObjectNode cmdParamObj = JSONUtils.parseObject(command.getCommandParam()); |
||||
int processInstanceId = cmdParamObj.path(CMD_PARAM_RECOVER_PROCESS_ID_STRING).asInt(); |
||||
|
||||
List<Command> commands = commandMapper.selectList(null); |
||||
// for all commands
|
||||
for (Command tmpCommand : commands) { |
||||
if (!cmdTypeMap.containsKey(tmpCommand.getCommandType())) { |
||||
continue; |
||||
} |
||||
ObjectNode tempObj = JSONUtils.parseObject(tmpCommand.getCommandParam()); |
||||
if (tempObj != null |
||||
&& processInstanceId == tempObj.path(CMD_PARAM_RECOVER_PROCESS_ID_STRING).asInt()) { |
||||
isNeedCreate = false; |
||||
break; |
||||
} |
||||
} |
||||
return isNeedCreate; |
||||
} |
||||
|
||||
@Override |
||||
public void createRecoveryWaitingThreadCommand(Command originCommand, ProcessInstance processInstance) { |
||||
// sub process doesn't need to create wait command
|
||||
if (processInstance.getIsSubProcess() == Flag.YES) { |
||||
if (originCommand != null) { |
||||
commandMapper.deleteById(originCommand.getId()); |
||||
} |
||||
return; |
||||
} |
||||
Map<String, String> cmdParam = new HashMap<>(); |
||||
cmdParam.put(Constants.CMD_PARAM_RECOVERY_WAITING_THREAD, String.valueOf(processInstance.getId())); |
||||
// process instance quit by "waiting thread" state
|
||||
if (originCommand == null) { |
||||
Command command = new Command( |
||||
CommandType.RECOVER_WAITING_THREAD, |
||||
processInstance.getTaskDependType(), |
||||
processInstance.getFailureStrategy(), |
||||
processInstance.getExecutorId(), |
||||
processInstance.getProcessDefinition().getCode(), |
||||
JSONUtils.toJsonString(cmdParam), |
||||
processInstance.getWarningType(), |
||||
processInstance.getWarningGroupId(), |
||||
processInstance.getScheduleTime(), |
||||
processInstance.getWorkerGroup(), |
||||
processInstance.getEnvironmentCode(), |
||||
processInstance.getProcessInstancePriority(), |
||||
processInstance.getDryRun(), |
||||
processInstance.getId(), |
||||
processInstance.getProcessDefinitionVersion(), |
||||
processInstance.getTestFlag()); |
||||
upsertCommand(command); |
||||
return; |
||||
} |
||||
|
||||
// update the command time if current command is recover from waiting
|
||||
if (originCommand.getCommandType() == CommandType.RECOVER_WAITING_THREAD) { |
||||
originCommand.setUpdateTime(new Date()); |
||||
upsertCommand(originCommand); |
||||
} else { |
||||
// delete old command and create new waiting thread command
|
||||
commandMapper.deleteById(originCommand.getId()); |
||||
originCommand.setId(0); |
||||
originCommand.setCommandType(CommandType.RECOVER_WAITING_THREAD); |
||||
originCommand.setUpdateTime(new Date()); |
||||
originCommand.setCommandParam(JSONUtils.toJsonString(cmdParam)); |
||||
originCommand.setProcessInstancePriority(processInstance.getProcessInstancePriority()); |
||||
upsertCommand(originCommand); |
||||
} |
||||
} |
||||
|
||||
private int upsertCommand(@NotNull Command command) { |
||||
if (command.getId() != null) { |
||||
return commandMapper.updateById(command); |
||||
} else { |
||||
return commandMapper.insert(command); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Command createSubProcessCommand(ProcessInstance parentProcessInstance, ProcessInstance childInstance, |
||||
ProcessInstanceMap instanceMap, TaskInstance task) { |
||||
CommandType commandType = getSubCommandType(parentProcessInstance, childInstance); |
||||
Map<String, Object> subProcessParam = JSONUtils.toMap(task.getTaskParams(), String.class, Object.class); |
||||
long childDefineCode = 0L; |
||||
if (subProcessParam.containsKey(Constants.CMD_PARAM_SUB_PROCESS_DEFINE_CODE)) { |
||||
try { |
||||
childDefineCode = |
||||
Long.parseLong( |
||||
String.valueOf(subProcessParam.get(Constants.CMD_PARAM_SUB_PROCESS_DEFINE_CODE))); |
||||
} catch (NumberFormatException nfe) { |
||||
logger.error("processDefinitionCode is not a number", nfe); |
||||
return null; |
||||
} |
||||
} |
||||
ProcessDefinition subProcessDefinition = processDefineMapper.queryByCode(childDefineCode); |
||||
|
||||
Object localParams = subProcessParam.get(Constants.LOCAL_PARAMS); |
||||
List<Property> allParam = JSONUtils.toList(JSONUtils.toJsonString(localParams), Property.class); |
||||
Map<String, String> globalMap = ParamUtils.getGlobalParamMap(task.getVarPool()); |
||||
Map<String, String> fatherParams = new HashMap<>(); |
||||
if (CollectionUtils.isNotEmpty(allParam)) { |
||||
for (Property info : allParam) { |
||||
if (Direct.OUT == info.getDirect()) { |
||||
continue; |
||||
} |
||||
fatherParams.put(info.getProp(), globalMap.get(info.getProp())); |
||||
} |
||||
} |
||||
String processParam = ParamUtils.getSubWorkFlowParam(instanceMap, parentProcessInstance, fatherParams); |
||||
int subProcessInstanceId = |
||||
childInstance == null ? 0 : (childInstance.getId() == null ? 0 : childInstance.getId()); |
||||
return new Command( |
||||
commandType, |
||||
TaskDependType.TASK_POST, |
||||
parentProcessInstance.getFailureStrategy(), |
||||
parentProcessInstance.getExecutorId(), |
||||
subProcessDefinition.getCode(), |
||||
processParam, |
||||
parentProcessInstance.getWarningType(), |
||||
parentProcessInstance.getWarningGroupId(), |
||||
parentProcessInstance.getScheduleTime(), |
||||
task.getWorkerGroup(), |
||||
task.getEnvironmentCode(), |
||||
parentProcessInstance.getProcessInstancePriority(), |
||||
parentProcessInstance.getDryRun(), |
||||
subProcessInstanceId, |
||||
subProcessDefinition.getVersion(), |
||||
parentProcessInstance.getTestFlag()); |
||||
} |
||||
|
||||
/** |
||||
* get sub work flow command type |
||||
* child instance exist: child command = fatherCommand |
||||
* child instance not exists: child command = fatherCommand[0] |
||||
*/ |
||||
private CommandType getSubCommandType(ProcessInstance parentProcessInstance, ProcessInstance childInstance) { |
||||
CommandType commandType = parentProcessInstance.getCommandType(); |
||||
if (childInstance == null) { |
||||
String fatherHistoryCommand = parentProcessInstance.getHistoryCmd(); |
||||
commandType = CommandType.valueOf(fatherHistoryCommand.split(Constants.COMMA)[0]); |
||||
} |
||||
return commandType; |
||||
} |
||||
} |
@ -0,0 +1,90 @@
|
||||
/* |
||||
* 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 static org.apache.dolphinscheduler.common.Constants.*; |
||||
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstanceMap; |
||||
import org.apache.dolphinscheduler.plugin.task.api.model.Property; |
||||
|
||||
import org.apache.commons.collections.MapUtils; |
||||
import org.apache.commons.lang3.StringUtils; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.stream.Collectors; |
||||
|
||||
import com.google.common.base.Strings; |
||||
|
||||
/** |
||||
* Param Utility class
|
||||
*/ |
||||
public class ParamUtils { |
||||
|
||||
/** |
||||
* convert globalParams string to global parameter map |
||||
* @param globalParams globalParams |
||||
* @return parameter map |
||||
*/ |
||||
public static Map<String, String> getGlobalParamMap(String globalParams) { |
||||
List<Property> propList; |
||||
Map<String, String> globalParamMap = new HashMap<>(); |
||||
if (!Strings.isNullOrEmpty(globalParams)) { |
||||
propList = JSONUtils.toList(globalParams, Property.class); |
||||
globalParamMap = propList.stream().collect(Collectors.toMap(Property::getProp, Property::getValue)); |
||||
} |
||||
return globalParamMap; |
||||
} |
||||
|
||||
/** |
||||
* Get sub workflow parameters |
||||
* @param instanceMap process instance map |
||||
* @param parentProcessInstance parent process instance |
||||
* @param fatherParams fatherParams |
||||
* @return sub workflow parameters |
||||
*/ |
||||
public static String getSubWorkFlowParam(ProcessInstanceMap instanceMap, ProcessInstance parentProcessInstance, |
||||
Map<String, String> fatherParams) { |
||||
// set sub work process command
|
||||
String processMapStr = JSONUtils.toJsonString(instanceMap); |
||||
Map<String, String> cmdParam = JSONUtils.toMap(processMapStr); |
||||
if (parentProcessInstance.isComplementData()) { |
||||
Map<String, String> parentParam = JSONUtils.toMap(parentProcessInstance.getCommandParam()); |
||||
String endTime = parentParam.get(CMDPARAM_COMPLEMENT_DATA_END_DATE); |
||||
String startTime = parentParam.get(CMDPARAM_COMPLEMENT_DATA_START_DATE); |
||||
String scheduleTime = parentParam.get(CMDPARAM_COMPLEMENT_DATA_SCHEDULE_DATE_LIST); |
||||
if (StringUtils.isNotEmpty(startTime) && StringUtils.isNotEmpty(endTime)) { |
||||
cmdParam.put(CMDPARAM_COMPLEMENT_DATA_END_DATE, endTime); |
||||
cmdParam.put(CMDPARAM_COMPLEMENT_DATA_START_DATE, startTime); |
||||
} |
||||
if (StringUtils.isNotEmpty(scheduleTime)) { |
||||
cmdParam.put(CMDPARAM_COMPLEMENT_DATA_SCHEDULE_DATE_LIST, scheduleTime); |
||||
} |
||||
processMapStr = JSONUtils.toJsonString(cmdParam); |
||||
} |
||||
if (MapUtils.isNotEmpty(fatherParams)) { |
||||
cmdParam.put(CMD_PARAM_FATHER_PARAMS, JSONUtils.toJsonString(fatherParams)); |
||||
processMapStr = JSONUtils.toJsonString(cmdParam); |
||||
} |
||||
return processMapStr; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,227 @@
|
||||
/* |
||||
* 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.command; |
||||
|
||||
import static org.apache.dolphinscheduler.common.Constants.CMD_PARAM_RECOVER_PROCESS_ID_STRING; |
||||
import static org.mockito.ArgumentMatchers.anyString; |
||||
|
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.CommandType; |
||||
import org.apache.dolphinscheduler.common.enums.Flag; |
||||
import org.apache.dolphinscheduler.common.enums.WarningType; |
||||
import org.apache.dolphinscheduler.common.utils.DateUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.Command; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessInstanceMap; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
import org.apache.dolphinscheduler.dao.mapper.CommandMapper; |
||||
import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionMapper; |
||||
import org.apache.dolphinscheduler.dao.mapper.ScheduleMapper; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.junit.jupiter.api.Assertions; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
import org.mockito.InjectMocks; |
||||
import org.mockito.Mock; |
||||
import org.mockito.Mockito; |
||||
import org.mockito.junit.jupiter.MockitoExtension; |
||||
import org.mockito.junit.jupiter.MockitoSettings; |
||||
import org.mockito.quality.Strictness; |
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
||||
@ExtendWith(MockitoExtension.class) |
||||
@MockitoSettings(strictness = Strictness.LENIENT) |
||||
class CommandServiceImplTest { |
||||
|
||||
@InjectMocks |
||||
private CommandServiceImpl commandService; |
||||
|
||||
@Mock |
||||
private CommandMapper commandMapper; |
||||
|
||||
@Mock |
||||
private ProcessDefinitionMapper processDefineMapper; |
||||
|
||||
@Mock |
||||
private ScheduleMapper scheduleMapper; |
||||
|
||||
@Test |
||||
public void testCreateSubCommand() { |
||||
ProcessInstance parentInstance = new ProcessInstance(); |
||||
parentInstance.setWarningType(WarningType.SUCCESS); |
||||
parentInstance.setWarningGroupId(0); |
||||
|
||||
TaskInstance task = new TaskInstance(); |
||||
task.setTaskParams("{\"processDefinitionCode\":10}}"); |
||||
task.setId(10); |
||||
task.setTaskCode(1L); |
||||
task.setTaskDefinitionVersion(1); |
||||
|
||||
ProcessInstance childInstance = null; |
||||
ProcessInstanceMap instanceMap = new ProcessInstanceMap(); |
||||
instanceMap.setParentProcessInstanceId(1); |
||||
instanceMap.setParentTaskInstanceId(10); |
||||
Command command; |
||||
|
||||
// father history: start; child null == command type: start
|
||||
parentInstance.setHistoryCmd("START_PROCESS"); |
||||
parentInstance.setCommandType(CommandType.START_PROCESS); |
||||
ProcessDefinition processDefinition = new ProcessDefinition(); |
||||
processDefinition.setCode(10L); |
||||
Mockito.when(processDefineMapper.queryByDefineId(100)).thenReturn(processDefinition); |
||||
Mockito.when(processDefineMapper.queryByCode(10L)).thenReturn(processDefinition); |
||||
command = commandService.createSubProcessCommand(parentInstance, childInstance, instanceMap, task); |
||||
Assertions.assertEquals(CommandType.START_PROCESS, command.getCommandType()); |
||||
|
||||
// father history: start,start failure; child null == command type: start
|
||||
parentInstance.setCommandType(CommandType.START_FAILURE_TASK_PROCESS); |
||||
parentInstance.setHistoryCmd("START_PROCESS,START_FAILURE_TASK_PROCESS"); |
||||
command = commandService.createSubProcessCommand(parentInstance, childInstance, instanceMap, task); |
||||
Assertions.assertEquals(CommandType.START_PROCESS, command.getCommandType()); |
||||
|
||||
// father history: scheduler,start failure; child null == command type: scheduler
|
||||
parentInstance.setCommandType(CommandType.START_FAILURE_TASK_PROCESS); |
||||
parentInstance.setHistoryCmd("SCHEDULER,START_FAILURE_TASK_PROCESS"); |
||||
command = commandService.createSubProcessCommand(parentInstance, childInstance, instanceMap, task); |
||||
Assertions.assertEquals(CommandType.SCHEDULER, command.getCommandType()); |
||||
|
||||
// father history: complement,start failure; child null == command type: complement
|
||||
|
||||
String startString = "2020-01-01 00:00:00"; |
||||
String endString = "2020-01-10 00:00:00"; |
||||
parentInstance.setCommandType(CommandType.START_FAILURE_TASK_PROCESS); |
||||
parentInstance.setHistoryCmd("COMPLEMENT_DATA,START_FAILURE_TASK_PROCESS"); |
||||
Map<String, String> complementMap = new HashMap<>(); |
||||
complementMap.put(Constants.CMDPARAM_COMPLEMENT_DATA_START_DATE, startString); |
||||
complementMap.put(Constants.CMDPARAM_COMPLEMENT_DATA_END_DATE, endString); |
||||
parentInstance.setCommandParam(JSONUtils.toJsonString(complementMap)); |
||||
command = commandService.createSubProcessCommand(parentInstance, childInstance, instanceMap, task); |
||||
Assertions.assertEquals(CommandType.COMPLEMENT_DATA, command.getCommandType()); |
||||
|
||||
JsonNode complementDate = JSONUtils.parseObject(command.getCommandParam()); |
||||
Date start = DateUtils.stringToDate(complementDate.get(Constants.CMDPARAM_COMPLEMENT_DATA_START_DATE).asText()); |
||||
Date end = DateUtils.stringToDate(complementDate.get(Constants.CMDPARAM_COMPLEMENT_DATA_END_DATE).asText()); |
||||
Assertions.assertEquals(startString, DateUtils.dateToString(start)); |
||||
Assertions.assertEquals(endString, DateUtils.dateToString(end)); |
||||
|
||||
// father history: start,failure,start failure; child not null == command type: start failure
|
||||
childInstance = new ProcessInstance(); |
||||
parentInstance.setCommandType(CommandType.START_FAILURE_TASK_PROCESS); |
||||
parentInstance.setHistoryCmd("START_PROCESS,START_FAILURE_TASK_PROCESS"); |
||||
command = commandService.createSubProcessCommand(parentInstance, childInstance, instanceMap, task); |
||||
Assertions.assertEquals(CommandType.START_FAILURE_TASK_PROCESS, command.getCommandType()); |
||||
} |
||||
|
||||
@Test |
||||
public void testVerifyIsNeedCreateCommand() { |
||||
|
||||
List<Command> commands = new ArrayList<>(); |
||||
|
||||
Command command = new Command(); |
||||
command.setCommandType(CommandType.REPEAT_RUNNING); |
||||
command.setCommandParam("{\"" + CMD_PARAM_RECOVER_PROCESS_ID_STRING + "\":\"111\"}"); |
||||
commands.add(command); |
||||
Mockito.when(commandMapper.selectList(null)).thenReturn(commands); |
||||
Assertions.assertFalse(commandService.verifyIsNeedCreateCommand(command)); |
||||
|
||||
Command command1 = new Command(); |
||||
command1.setCommandType(CommandType.REPEAT_RUNNING); |
||||
command1.setCommandParam("{\"" + CMD_PARAM_RECOVER_PROCESS_ID_STRING + "\":\"222\"}"); |
||||
Assertions.assertTrue(commandService.verifyIsNeedCreateCommand(command1)); |
||||
|
||||
Command command2 = new Command(); |
||||
command2.setCommandType(CommandType.PAUSE); |
||||
Assertions.assertTrue(commandService.verifyIsNeedCreateCommand(command2)); |
||||
} |
||||
|
||||
@Test |
||||
public void testCreateRecoveryWaitingThreadCommand() { |
||||
int id = 123; |
||||
Mockito.when(commandMapper.deleteById(id)).thenReturn(1); |
||||
ProcessInstance subProcessInstance = new ProcessInstance(); |
||||
subProcessInstance.setIsSubProcess(Flag.YES); |
||||
Command originCommand = new Command(); |
||||
originCommand.setId(id); |
||||
commandService.createRecoveryWaitingThreadCommand(originCommand, subProcessInstance); |
||||
|
||||
ProcessInstance processInstance = new ProcessInstance(); |
||||
processInstance.setId(111); |
||||
commandService.createRecoveryWaitingThreadCommand(null, subProcessInstance); |
||||
|
||||
Command recoverCommand = new Command(); |
||||
recoverCommand.setCommandType(CommandType.RECOVER_WAITING_THREAD); |
||||
commandService.createRecoveryWaitingThreadCommand(recoverCommand, subProcessInstance); |
||||
|
||||
Command repeatRunningCommand = new Command(); |
||||
recoverCommand.setCommandType(CommandType.REPEAT_RUNNING); |
||||
commandService.createRecoveryWaitingThreadCommand(repeatRunningCommand, subProcessInstance); |
||||
|
||||
ProcessInstance subProcessInstance2 = new ProcessInstance(); |
||||
subProcessInstance2.setId(111); |
||||
subProcessInstance2.setIsSubProcess(Flag.NO); |
||||
commandService.createRecoveryWaitingThreadCommand(repeatRunningCommand, subProcessInstance2); |
||||
} |
||||
|
||||
@Test |
||||
public void giveNullOriginCommand_thenCreateRecoveryWaitingThreadCommand_expectNoDelete() { |
||||
ProcessInstance subProcessInstance = new ProcessInstance(); |
||||
subProcessInstance.setIsSubProcess(Flag.NO); |
||||
subProcessInstance.setId(111); |
||||
ProcessDefinition processDefinition = new ProcessDefinition(); |
||||
processDefinition.setId(111); |
||||
processDefinition.setCode(10L); |
||||
subProcessInstance.setProcessDefinition(processDefinition); |
||||
subProcessInstance.setWarningGroupId(1); |
||||
commandService.createRecoveryWaitingThreadCommand(null, subProcessInstance); |
||||
Mockito.verify(commandMapper, Mockito.times(0)).deleteById(anyString()); |
||||
} |
||||
|
||||
@Test |
||||
public void testCreateCommand() { |
||||
Command command = new Command(); |
||||
command.setProcessDefinitionCode(123); |
||||
command.setCommandParam("{\"ProcessInstanceId\":222}"); |
||||
command.setCommandType(CommandType.START_PROCESS); |
||||
int mockResult = 1; |
||||
Mockito.when(commandMapper.insert(command)).thenReturn(mockResult); |
||||
int exeMethodResult = commandService.createCommand(command); |
||||
Assertions.assertEquals(mockResult, exeMethodResult); |
||||
Mockito.verify(commandMapper, Mockito.times(1)).insert(command); |
||||
} |
||||
|
||||
@Test |
||||
public void testFindCommandPageBySlot() { |
||||
int pageSize = 1; |
||||
int pageNumber = 0; |
||||
int masterCount = 0; |
||||
int thisMasterSlot = 2; |
||||
List<Command> commandList = |
||||
commandService.findCommandPageBySlot(pageSize, pageNumber, masterCount, thisMasterSlot); |
||||
Assertions.assertEquals(0, commandList.size()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,37 @@
|
||||
/* |
||||
* 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 java.util.Map; |
||||
|
||||
import org.junit.jupiter.api.Assertions; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
public class ParamUtilsTest { |
||||
|
||||
@Test |
||||
public void testGetGlobalParamMap() { |
||||
String globalParam = "[{\"prop\":\"startParam1\",\"direct\":\"IN\",\"type\":\"VARCHAR\",\"value\":\"\"}]"; |
||||
Map<String, String> globalParamMap = ParamUtils.getGlobalParamMap(globalParam); |
||||
Assertions.assertEquals(globalParamMap.size(), 1); |
||||
Assertions.assertEquals(globalParamMap.get("startParam1"), ""); |
||||
|
||||
Map<String, String> emptyParamMap = ParamUtils.getGlobalParamMap(null); |
||||
Assertions.assertEquals(emptyParamMap.size(), 0); |
||||
} |
||||
} |
Loading…
Reference in new issue