You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1157 lines
54 KiB
1157 lines
54 KiB
/* |
|
* 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.api.service.impl; |
|
|
|
import static org.apache.dolphinscheduler.api.constants.ApiFuncIdentificationConstant.WORKFLOW_INSTANCE; |
|
import static org.apache.dolphinscheduler.api.enums.Status.PROCESS_INSTANCE_NOT_EXIST; |
|
import static org.apache.dolphinscheduler.api.enums.Status.PROCESS_INSTANCE_STATE_OPERATION_ERROR; |
|
import static org.apache.dolphinscheduler.common.constants.Constants.DATA_LIST; |
|
import static org.apache.dolphinscheduler.common.constants.Constants.DEPENDENT_SPLIT; |
|
import static org.apache.dolphinscheduler.common.constants.Constants.GLOBAL_PARAMS; |
|
import static org.apache.dolphinscheduler.common.constants.Constants.LOCAL_PARAMS; |
|
import static org.apache.dolphinscheduler.common.constants.Constants.PROCESS_INSTANCE_STATE; |
|
import static org.apache.dolphinscheduler.common.constants.Constants.TASK_LIST; |
|
import static org.apache.dolphinscheduler.plugin.task.api.TaskConstants.TASK_TYPE_DEPENDENT; |
|
import static org.apache.dolphinscheduler.plugin.task.api.TaskConstants.TASK_TYPE_SUB_PROCESS; |
|
|
|
import org.apache.dolphinscheduler.api.constants.ApiFuncIdentificationConstant; |
|
import org.apache.dolphinscheduler.api.dto.DynamicSubWorkflowDto; |
|
import org.apache.dolphinscheduler.api.dto.gantt.GanttDto; |
|
import org.apache.dolphinscheduler.api.dto.gantt.Task; |
|
import org.apache.dolphinscheduler.api.dto.workflowInstance.WorkflowInstanceQueryRequest; |
|
import org.apache.dolphinscheduler.api.enums.Status; |
|
import org.apache.dolphinscheduler.api.exceptions.ServiceException; |
|
import org.apache.dolphinscheduler.api.service.ExecutorService; |
|
import org.apache.dolphinscheduler.api.service.LoggerService; |
|
import org.apache.dolphinscheduler.api.service.ProcessDefinitionService; |
|
import org.apache.dolphinscheduler.api.service.ProcessInstanceService; |
|
import org.apache.dolphinscheduler.api.service.ProjectService; |
|
import org.apache.dolphinscheduler.api.service.TaskInstanceService; |
|
import org.apache.dolphinscheduler.api.service.UsersService; |
|
import org.apache.dolphinscheduler.api.utils.PageInfo; |
|
import org.apache.dolphinscheduler.api.utils.Result; |
|
import org.apache.dolphinscheduler.common.constants.CommandKeyConstants; |
|
import org.apache.dolphinscheduler.common.constants.Constants; |
|
import org.apache.dolphinscheduler.common.enums.Flag; |
|
import org.apache.dolphinscheduler.common.enums.WorkflowExecutionStatus; |
|
import org.apache.dolphinscheduler.common.graph.DAG; |
|
import org.apache.dolphinscheduler.common.model.TaskNodeRelation; |
|
import org.apache.dolphinscheduler.common.utils.DateUtils; |
|
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
|
import org.apache.dolphinscheduler.common.utils.placeholder.BusinessTimeUtils; |
|
import org.apache.dolphinscheduler.dao.AlertDao; |
|
import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; |
|
import org.apache.dolphinscheduler.dao.entity.ProcessInstance; |
|
import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog; |
|
import org.apache.dolphinscheduler.dao.entity.Project; |
|
import org.apache.dolphinscheduler.dao.entity.RelationSubWorkflow; |
|
import org.apache.dolphinscheduler.dao.entity.ResponseTaskLog; |
|
import org.apache.dolphinscheduler.dao.entity.TaskDefinition; |
|
import org.apache.dolphinscheduler.dao.entity.TaskDefinitionLog; |
|
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
|
import org.apache.dolphinscheduler.dao.entity.User; |
|
import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionLogMapper; |
|
import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionMapper; |
|
import org.apache.dolphinscheduler.dao.mapper.ProcessInstanceMapper; |
|
import org.apache.dolphinscheduler.dao.mapper.ProjectMapper; |
|
import org.apache.dolphinscheduler.dao.mapper.RelationSubWorkflowMapper; |
|
import org.apache.dolphinscheduler.dao.mapper.ScheduleMapper; |
|
import org.apache.dolphinscheduler.dao.mapper.TaskDefinitionLogMapper; |
|
import org.apache.dolphinscheduler.dao.mapper.TaskDefinitionMapper; |
|
import org.apache.dolphinscheduler.dao.mapper.TaskInstanceMapper; |
|
import org.apache.dolphinscheduler.dao.mapper.TenantMapper; |
|
import org.apache.dolphinscheduler.dao.repository.ProcessInstanceDao; |
|
import org.apache.dolphinscheduler.dao.repository.ProcessInstanceMapDao; |
|
import org.apache.dolphinscheduler.dao.repository.TaskInstanceDao; |
|
import org.apache.dolphinscheduler.dao.utils.WorkflowUtils; |
|
import org.apache.dolphinscheduler.plugin.task.api.TaskPluginManager; |
|
import org.apache.dolphinscheduler.plugin.task.api.enums.DependResult; |
|
import org.apache.dolphinscheduler.plugin.task.api.model.Property; |
|
import org.apache.dolphinscheduler.plugin.task.api.parameters.ParametersNode; |
|
import org.apache.dolphinscheduler.plugin.task.api.utils.ParameterUtils; |
|
import org.apache.dolphinscheduler.service.expand.CuringParamsService; |
|
import org.apache.dolphinscheduler.service.model.TaskNode; |
|
import org.apache.dolphinscheduler.service.process.ProcessService; |
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
|
import java.io.BufferedReader; |
|
import java.io.ByteArrayInputStream; |
|
import java.io.IOException; |
|
import java.io.InputStreamReader; |
|
import java.nio.charset.StandardCharsets; |
|
import java.util.ArrayList; |
|
import java.util.Collections; |
|
import java.util.Comparator; |
|
import java.util.Date; |
|
import java.util.HashMap; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.Objects; |
|
import java.util.function.Function; |
|
import java.util.stream.Collectors; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
import org.springframework.context.annotation.Lazy; |
|
import org.springframework.stereotype.Service; |
|
import org.springframework.transaction.annotation.Transactional; |
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage; |
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|
|
|
/** |
|
* process instance service impl |
|
*/ |
|
@Service |
|
@Slf4j |
|
public class ProcessInstanceServiceImpl extends BaseServiceImpl implements ProcessInstanceService { |
|
|
|
public static final String TASK_TYPE = "taskType"; |
|
|
|
public static final String LOCAL_PARAMS_LIST = "localParamsList"; |
|
|
|
@Autowired |
|
ProjectMapper projectMapper; |
|
|
|
@Autowired |
|
ProjectService projectService; |
|
|
|
@Autowired |
|
ProcessService processService; |
|
|
|
@Autowired |
|
TaskInstanceDao taskInstanceDao; |
|
|
|
@Lazy |
|
@Autowired |
|
private TaskInstanceService taskInstanceService; |
|
|
|
@Autowired |
|
ProcessInstanceMapper processInstanceMapper; |
|
|
|
@Autowired |
|
ProcessInstanceDao processInstanceDao; |
|
|
|
@Autowired |
|
private ProcessInstanceMapDao processInstanceMapDao; |
|
|
|
@Autowired |
|
ProcessDefinitionMapper processDefineMapper; |
|
|
|
@Autowired |
|
ProcessDefinitionService processDefinitionService; |
|
|
|
@Autowired |
|
ExecutorService execService; |
|
|
|
@Autowired |
|
TaskInstanceMapper taskInstanceMapper; |
|
|
|
@Autowired |
|
LoggerService loggerService; |
|
|
|
@Autowired |
|
ProcessDefinitionLogMapper processDefinitionLogMapper; |
|
|
|
@Autowired |
|
TaskDefinitionLogMapper taskDefinitionLogMapper; |
|
|
|
@Autowired |
|
UsersService usersService; |
|
|
|
@Autowired |
|
private TenantMapper tenantMapper; |
|
|
|
@Autowired |
|
TaskDefinitionMapper taskDefinitionMapper; |
|
|
|
@Autowired |
|
private TaskPluginManager taskPluginManager; |
|
|
|
@Autowired |
|
private ScheduleMapper scheduleMapper; |
|
|
|
@Autowired |
|
private RelationSubWorkflowMapper relationSubWorkflowMapper; |
|
|
|
@Autowired |
|
private AlertDao alertDao; |
|
|
|
@Autowired |
|
private CuringParamsService curingGlobalParamsService; |
|
|
|
/** |
|
* return top n SUCCESS process instance order by running time which started between startTime and endTime |
|
*/ |
|
@Override |
|
public Map<String, Object> queryTopNLongestRunningProcessInstance(User loginUser, long projectCode, int size, |
|
String startTime, String endTime) { |
|
Project project = projectMapper.queryByCode(projectCode); |
|
// check user access for project |
|
Map<String, Object> result = |
|
projectService.checkProjectAndAuth(loginUser, project, projectCode, |
|
ApiFuncIdentificationConstant.WORKFLOW_INSTANCE); |
|
if (result.get(Constants.STATUS) != Status.SUCCESS) { |
|
return result; |
|
} |
|
|
|
if (0 > size) { |
|
putMsg(result, Status.NEGTIVE_SIZE_NUMBER_ERROR, size); |
|
return result; |
|
} |
|
if (Objects.isNull(startTime)) { |
|
putMsg(result, Status.DATA_IS_NULL, Constants.START_TIME); |
|
return result; |
|
} |
|
Date start = DateUtils.stringToDate(startTime); |
|
if (Objects.isNull(endTime)) { |
|
putMsg(result, Status.DATA_IS_NULL, Constants.END_TIME); |
|
return result; |
|
} |
|
Date end = DateUtils.stringToDate(endTime); |
|
if (start == null || end == null) { |
|
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, Constants.START_END_DATE); |
|
return result; |
|
} |
|
if (start.getTime() > end.getTime()) { |
|
putMsg(result, Status.START_TIME_BIGGER_THAN_END_TIME_ERROR, startTime, endTime); |
|
return result; |
|
} |
|
|
|
List<ProcessInstance> processInstances = processInstanceMapper.queryTopNProcessInstance(size, start, end, |
|
WorkflowExecutionStatus.SUCCESS, projectCode); |
|
result.put(DATA_LIST, processInstances); |
|
putMsg(result, Status.SUCCESS); |
|
return result; |
|
} |
|
|
|
/** |
|
* query process instance by id |
|
* |
|
* @param loginUser login user |
|
* @param projectCode project code |
|
* @param processId process instance id |
|
* @return process instance detail |
|
*/ |
|
@Override |
|
public Map<String, Object> queryProcessInstanceById(User loginUser, long projectCode, Integer processId) { |
|
Project project = projectMapper.queryByCode(projectCode); |
|
// check user access for project |
|
Map<String, Object> result = |
|
projectService.checkProjectAndAuth(loginUser, project, projectCode, |
|
ApiFuncIdentificationConstant.WORKFLOW_INSTANCE); |
|
if (result.get(Constants.STATUS) != Status.SUCCESS) { |
|
return result; |
|
} |
|
ProcessInstance processInstance = processService.findProcessInstanceDetailById(processId) |
|
.orElseThrow(() -> new ServiceException(PROCESS_INSTANCE_NOT_EXIST, processId)); |
|
|
|
ProcessDefinition processDefinition = |
|
processService.findProcessDefinition(processInstance.getProcessDefinitionCode(), |
|
processInstance.getProcessDefinitionVersion()); |
|
|
|
if (processDefinition == null || projectCode != processDefinition.getProjectCode()) { |
|
log.error("Process definition does not exist, projectCode:{}.", projectCode); |
|
putMsg(result, Status.PROCESS_DEFINE_NOT_EXIST, processId); |
|
} else { |
|
processInstance.setLocations(processDefinition.getLocations()); |
|
processInstance.setDagData(processService.genDagData(processDefinition)); |
|
result.put(DATA_LIST, processInstance); |
|
putMsg(result, Status.SUCCESS); |
|
} |
|
|
|
return result; |
|
} |
|
|
|
@Override |
|
public ProcessInstance queryByWorkflowInstanceIdThrowExceptionIfNotFound(Integer workflowInstanceId) { |
|
ProcessInstance processInstance = processInstanceDao.queryById(workflowInstanceId); |
|
if (processInstance == null) { |
|
throw new ServiceException(PROCESS_INSTANCE_NOT_EXIST, workflowInstanceId); |
|
} |
|
return processInstance; |
|
} |
|
|
|
/** |
|
* query workflow instance by id |
|
* |
|
* @param loginUser login user |
|
* @param workflowInstanceId workflow instance id |
|
* @return workflow instance detail |
|
*/ |
|
@Override |
|
public Map<String, Object> queryProcessInstanceById(User loginUser, Integer workflowInstanceId) { |
|
ProcessInstance processInstance = processInstanceMapper.selectById(workflowInstanceId); |
|
ProcessDefinition processDefinition = |
|
processDefineMapper.queryByCode(processInstance.getProcessDefinitionCode()); |
|
|
|
return queryProcessInstanceById(loginUser, processDefinition.getProjectCode(), workflowInstanceId); |
|
} |
|
|
|
/** |
|
* paging query process instance list, filtering according to project, process definition, time range, keyword, process status |
|
* |
|
* @param loginUser login user |
|
* @param projectCode project code |
|
* @param processDefineCode process definition code |
|
* @param pageNo page number |
|
* @param pageSize page size |
|
* @param searchVal search value |
|
* @param stateType state type |
|
* @param host host |
|
* @param startDate start time |
|
* @param endDate end time |
|
* @param otherParamsJson otherParamsJson handle other params |
|
* @return process instance list |
|
*/ |
|
@Override |
|
public Result<PageInfo<ProcessInstance>> queryProcessInstanceList(User loginUser, |
|
long projectCode, |
|
long processDefineCode, |
|
String startDate, |
|
String endDate, |
|
String searchVal, |
|
String executorName, |
|
WorkflowExecutionStatus stateType, |
|
String host, |
|
String otherParamsJson, |
|
Integer pageNo, |
|
Integer pageSize) { |
|
|
|
Result result = new Result(); |
|
// check user access for project |
|
projectService.checkProjectAndAuthThrowException(loginUser, projectCode, WORKFLOW_INSTANCE); |
|
|
|
int[] statusArray = null; |
|
// filter by state |
|
if (stateType != null) { |
|
statusArray = new int[]{stateType.getCode()}; |
|
} |
|
|
|
Date start = checkAndParseDateParameters(startDate); |
|
Date end = checkAndParseDateParameters(endDate); |
|
|
|
Page<ProcessInstance> page = new Page<>(pageNo, pageSize); |
|
PageInfo<ProcessInstance> pageInfo = new PageInfo<>(pageNo, pageSize); |
|
|
|
IPage<ProcessInstance> processInstanceList = processInstanceMapper.queryProcessInstanceListPaging( |
|
page, |
|
projectCode, |
|
processDefineCode, |
|
searchVal, |
|
executorName, |
|
statusArray, |
|
host, |
|
start, |
|
end); |
|
|
|
List<ProcessInstance> processInstances = processInstanceList.getRecords(); |
|
List<Integer> userIds = Collections.emptyList(); |
|
if (CollectionUtils.isNotEmpty(processInstances)) { |
|
userIds = processInstances.stream().map(ProcessInstance::getExecutorId).collect(Collectors.toList()); |
|
} |
|
List<User> users = usersService.queryUser(userIds); |
|
Map<Integer, User> idToUserMap = Collections.emptyMap(); |
|
if (CollectionUtils.isNotEmpty(users)) { |
|
idToUserMap = users.stream().collect(Collectors.toMap(User::getId, Function.identity())); |
|
} |
|
|
|
for (ProcessInstance processInstance : processInstances) { |
|
processInstance.setDuration(WorkflowUtils.getWorkflowInstanceDuration(processInstance)); |
|
User executor = idToUserMap.get(processInstance.getExecutorId()); |
|
if (null != executor) { |
|
processInstance.setExecutorName(executor.getUserName()); |
|
} |
|
} |
|
|
|
pageInfo.setTotal((int) processInstanceList.getTotal()); |
|
pageInfo.setTotalList(processInstances); |
|
result.setData(pageInfo); |
|
putMsg(result, Status.SUCCESS); |
|
return result; |
|
} |
|
|
|
/** |
|
* paging query process instance list, filtering according to project, process definition, time range, keyword, process status |
|
* |
|
* @param loginUser login user |
|
* @param workflowInstanceQueryRequest workflowInstanceQueryRequest |
|
* @return process instance list |
|
*/ |
|
@Override |
|
public Result queryProcessInstanceList(User loginUser, WorkflowInstanceQueryRequest workflowInstanceQueryRequest) { |
|
Result result = new Result(); |
|
ProcessInstance processInstance = workflowInstanceQueryRequest.convert2ProcessInstance(); |
|
String projectName = workflowInstanceQueryRequest.getProjectName(); |
|
if (!StringUtils.isBlank(projectName)) { |
|
Project project = projectMapper.queryByName(projectName); |
|
projectService.checkProjectAndAuthThrowException(loginUser, project, |
|
ApiFuncIdentificationConstant.WORKFLOW_DEFINITION); |
|
ProcessDefinition processDefinition = |
|
processDefineMapper.queryByDefineName(project.getCode(), processInstance.getName()); |
|
processInstance.setProcessDefinitionCode(processDefinition.getCode()); |
|
processInstance.setProjectCode(project.getCode()); |
|
} |
|
|
|
Page<ProcessInstance> page = |
|
new Page<>(workflowInstanceQueryRequest.getPageNo(), workflowInstanceQueryRequest.getPageSize()); |
|
PageInfo<ProcessInstance> pageInfo = |
|
new PageInfo<>(workflowInstanceQueryRequest.getPageNo(), workflowInstanceQueryRequest.getPageSize()); |
|
|
|
IPage<ProcessInstance> processInstanceList = processInstanceMapper.queryProcessInstanceListV2Paging( |
|
page, |
|
processInstance.getProjectCode(), |
|
processInstance.getProcessDefinitionCode(), |
|
processInstance.getName(), |
|
workflowInstanceQueryRequest.getStartTime(), |
|
workflowInstanceQueryRequest.getEndTime(), |
|
workflowInstanceQueryRequest.getState(), |
|
processInstance.getHost()); |
|
|
|
List<ProcessInstance> processInstances = processInstanceList.getRecords(); |
|
List<Integer> userIds = Collections.emptyList(); |
|
if (CollectionUtils.isNotEmpty(processInstances)) { |
|
userIds = processInstances.stream().map(ProcessInstance::getExecutorId).collect(Collectors.toList()); |
|
} |
|
List<User> users = usersService.queryUser(userIds); |
|
Map<Integer, User> idToUserMap = Collections.emptyMap(); |
|
if (CollectionUtils.isNotEmpty(users)) { |
|
idToUserMap = users.stream().collect(Collectors.toMap(User::getId, Function.identity())); |
|
} |
|
|
|
for (ProcessInstance Instance : processInstances) { |
|
Instance.setDuration(WorkflowUtils.getWorkflowInstanceDuration(Instance)); |
|
User executor = idToUserMap.get(Instance.getExecutorId()); |
|
if (null != executor) { |
|
Instance.setExecutorName(executor.getUserName()); |
|
} |
|
} |
|
|
|
pageInfo.setTotal((int) processInstanceList.getTotal()); |
|
pageInfo.setTotalList(processInstances); |
|
result.setData(pageInfo); |
|
putMsg(result, Status.SUCCESS); |
|
return result; |
|
} |
|
|
|
/** |
|
* query task list by process instance id |
|
* |
|
* @param loginUser login user |
|
* @param projectCode project code |
|
* @param processId process instance id |
|
* @return task list for the process instance |
|
* @throws IOException io exception |
|
*/ |
|
@Override |
|
public Map<String, Object> queryTaskListByProcessId(User loginUser, long projectCode, |
|
Integer processId) throws IOException { |
|
Project project = projectMapper.queryByCode(projectCode); |
|
// check user access for project |
|
Map<String, Object> result = |
|
projectService.checkProjectAndAuth(loginUser, project, projectCode, |
|
ApiFuncIdentificationConstant.WORKFLOW_INSTANCE); |
|
if (result.get(Constants.STATUS) != Status.SUCCESS) { |
|
return result; |
|
} |
|
ProcessInstance processInstance = processService.findProcessInstanceDetailById(processId) |
|
.orElseThrow(() -> new ServiceException(PROCESS_INSTANCE_NOT_EXIST, processId)); |
|
ProcessDefinition processDefinition = |
|
processDefineMapper.queryByCode(processInstance.getProcessDefinitionCode()); |
|
if (processDefinition != null && projectCode != processDefinition.getProjectCode()) { |
|
log.error("Process definition does not exist, projectCode:{}, processDefinitionId:{}.", projectCode, |
|
processId); |
|
putMsg(result, PROCESS_INSTANCE_NOT_EXIST, processId); |
|
return result; |
|
} |
|
List<TaskInstance> taskInstanceList = |
|
taskInstanceDao.queryValidTaskListByWorkflowInstanceId(processId, processInstance.getTestFlag()); |
|
addDependResultForTaskList(loginUser, taskInstanceList); |
|
Map<String, Object> resultMap = new HashMap<>(); |
|
resultMap.put(PROCESS_INSTANCE_STATE, processInstance.getState().toString()); |
|
resultMap.put(TASK_LIST, taskInstanceList); |
|
result.put(DATA_LIST, resultMap); |
|
|
|
putMsg(result, Status.SUCCESS); |
|
return result; |
|
} |
|
|
|
@Override |
|
public List<DynamicSubWorkflowDto> queryDynamicSubWorkflowInstances(User loginUser, Integer taskId) { |
|
TaskInstance taskInstance = taskInstanceDao.queryById(taskId); |
|
Map<String, Object> result = new HashMap<>(); |
|
if (taskInstance == null) { |
|
putMsg(result, Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
|
throw new ServiceException(Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
|
} |
|
|
|
TaskDefinition taskDefinition = taskDefinitionMapper.queryByCode(taskInstance.getTaskCode()); |
|
if (taskDefinition == null) { |
|
putMsg(result, Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
|
throw new ServiceException(Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
|
} |
|
|
|
if (!taskInstance.isDynamic()) { |
|
putMsg(result, Status.TASK_INSTANCE_NOT_DYNAMIC_TASK, taskInstance.getName()); |
|
throw new ServiceException(Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
|
} |
|
List<RelationSubWorkflow> relationSubWorkflows = relationSubWorkflowMapper |
|
.queryAllSubProcessInstance((long) taskInstance.getProcessInstanceId(), |
|
taskInstance.getTaskCode()); |
|
List<Long> allSubProcessInstanceId = relationSubWorkflows.stream() |
|
.map(RelationSubWorkflow::getSubWorkflowInstanceId).collect(java.util.stream.Collectors.toList()); |
|
List<ProcessInstance> allSubWorkflows = processInstanceDao.queryByIds(allSubProcessInstanceId); |
|
|
|
if (allSubWorkflows == null || allSubWorkflows.isEmpty()) { |
|
putMsg(result, Status.SUB_PROCESS_INSTANCE_NOT_EXIST, taskId); |
|
throw new ServiceException(Status.SUB_PROCESS_INSTANCE_NOT_EXIST, taskId); |
|
} |
|
Long subWorkflowCode = allSubWorkflows.get(0).getProcessDefinitionCode(); |
|
int subWorkflowVersion = allSubWorkflows.get(0).getProcessDefinitionVersion(); |
|
ProcessDefinition subProcessDefinition = |
|
processService.findProcessDefinition(subWorkflowCode, subWorkflowVersion); |
|
if (subProcessDefinition == null) { |
|
putMsg(result, Status.PROCESS_DEFINE_NOT_EXIST, subWorkflowCode); |
|
throw new ServiceException(Status.PROCESS_DEFINE_NOT_EXIST, subWorkflowCode); |
|
} |
|
|
|
allSubWorkflows.sort(Comparator.comparing(ProcessInstance::getId)); |
|
|
|
List<DynamicSubWorkflowDto> allDynamicSubWorkflowDtos = new ArrayList<>(); |
|
int index = 1; |
|
for (ProcessInstance processInstance : allSubWorkflows) { |
|
DynamicSubWorkflowDto dynamicSubWorkflowDto = new DynamicSubWorkflowDto(); |
|
dynamicSubWorkflowDto.setProcessInstanceId(processInstance.getId()); |
|
dynamicSubWorkflowDto.setIndex(index); |
|
dynamicSubWorkflowDto.setState(processInstance.getState()); |
|
dynamicSubWorkflowDto.setName(subProcessDefinition.getName()); |
|
Map<String, String> commandParamMap = JSONUtils.toMap(processInstance.getCommandParam()); |
|
String parameter = commandParamMap.get(CommandKeyConstants.CMD_DYNAMIC_START_PARAMS); |
|
dynamicSubWorkflowDto.setParameters(JSONUtils.toMap(parameter)); |
|
allDynamicSubWorkflowDtos.add(dynamicSubWorkflowDto); |
|
index++; |
|
|
|
} |
|
|
|
return allDynamicSubWorkflowDtos; |
|
} |
|
|
|
/** |
|
* add dependent result for dependent task |
|
*/ |
|
private void addDependResultForTaskList(User loginUser, List<TaskInstance> taskInstanceList) throws IOException { |
|
for (TaskInstance taskInstance : taskInstanceList) { |
|
if (TASK_TYPE_DEPENDENT.equalsIgnoreCase(taskInstance.getTaskType())) { |
|
log.info("DEPENDENT type task instance need to set dependent result, taskCode:{}, taskInstanceId:{}", |
|
taskInstance.getTaskCode(), taskInstance.getId()); |
|
// TODO The result of dependent item should not be obtained from the log, waiting for optimization. |
|
Result<ResponseTaskLog> logResult = loggerService.queryLog(loginUser, |
|
taskInstance.getId(), Constants.LOG_QUERY_SKIP_LINE_NUMBER, Constants.LOG_QUERY_LIMIT); |
|
if (logResult.getCode() == Status.SUCCESS.ordinal()) { |
|
String log = logResult.getData().getMessage(); |
|
Map<String, DependResult> resultMap = parseLogForDependentResult(log); |
|
taskInstance.setDependentResult(JSONUtils.toJsonString(resultMap)); |
|
} |
|
} |
|
} |
|
} |
|
|
|
@Override |
|
public Map<String, DependResult> parseLogForDependentResult(String content) throws IOException { |
|
Map<String, DependResult> resultMap = new HashMap<>(); |
|
if (StringUtils.isEmpty(content)) { |
|
log.warn("Log content is empty."); |
|
return resultMap; |
|
} |
|
|
|
BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(content.getBytes( |
|
StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); |
|
String line; |
|
while ((line = br.readLine()) != null) { |
|
if (line.contains(DEPENDENT_SPLIT)) { |
|
String[] tmpStringArray = line.split(":\\|\\|"); |
|
if (tmpStringArray.length != 2) { |
|
continue; |
|
} |
|
String dependResultString = tmpStringArray[1]; |
|
String[] dependStringArray = dependResultString.split(","); |
|
if (dependStringArray.length != 3) { |
|
continue; |
|
} |
|
String key = dependStringArray[0].trim().split(":")[1].trim(); |
|
String result = dependStringArray[1].trim().split(":")[1].trim(); |
|
DependResult dependResult = DependResult.valueOf(result); |
|
resultMap.put(key, dependResult); |
|
} |
|
} |
|
return resultMap; |
|
} |
|
|
|
/** |
|
* query sub process instance detail info by task id |
|
* |
|
* @param loginUser login user |
|
* @param projectCode project code |
|
* @param taskId task id |
|
* @return sub process instance detail |
|
*/ |
|
@Override |
|
public Map<String, Object> querySubProcessInstanceByTaskId(User loginUser, long projectCode, Integer taskId) { |
|
Project project = projectMapper.queryByCode(projectCode); |
|
// check user access for project |
|
Map<String, Object> result = |
|
projectService.checkProjectAndAuth(loginUser, project, projectCode, |
|
ApiFuncIdentificationConstant.WORKFLOW_INSTANCE); |
|
if (result.get(Constants.STATUS) != Status.SUCCESS) { |
|
return result; |
|
} |
|
|
|
TaskInstance taskInstance = taskInstanceDao.queryById(taskId); |
|
if (taskInstance == null) { |
|
log.error("Task instance does not exist, projectCode:{}, taskInstanceId{}.", projectCode, taskId); |
|
putMsg(result, Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
|
return result; |
|
} |
|
|
|
TaskDefinition taskDefinition = taskDefinitionMapper.queryByCode(taskInstance.getTaskCode()); |
|
if (taskDefinition != null && projectCode != taskDefinition.getProjectCode()) { |
|
log.error("Task definition does not exist, projectCode:{}, taskDefinitionCode:{}.", projectCode, |
|
taskInstance.getTaskCode()); |
|
putMsg(result, Status.TASK_INSTANCE_NOT_EXISTS, taskId); |
|
return result; |
|
} |
|
|
|
if (!taskInstance.isSubProcess()) { |
|
log.warn("Task instance is not {} type instance, projectCode:{}, taskInstanceId:{}.", |
|
TASK_TYPE_SUB_PROCESS, projectCode, taskId); |
|
putMsg(result, Status.TASK_INSTANCE_NOT_SUB_WORKFLOW_INSTANCE, taskInstance.getName()); |
|
return result; |
|
} |
|
|
|
ProcessInstance subWorkflowInstance = processService.findSubProcessInstance( |
|
taskInstance.getProcessInstanceId(), taskInstance.getId()); |
|
if (subWorkflowInstance == null) { |
|
log.error("SubProcess instance does not exist, projectCode:{}, taskInstanceId:{}.", projectCode, |
|
taskInstance.getId()); |
|
putMsg(result, Status.SUB_PROCESS_INSTANCE_NOT_EXIST, taskId); |
|
return result; |
|
} |
|
Map<String, Object> dataMap = new HashMap<>(); |
|
dataMap.put(Constants.SUBPROCESS_INSTANCE_ID, subWorkflowInstance.getId()); |
|
result.put(DATA_LIST, dataMap); |
|
putMsg(result, Status.SUCCESS); |
|
return result; |
|
} |
|
|
|
/** |
|
* update process instance |
|
* |
|
* @param loginUser login user |
|
* @param projectCode project code |
|
* @param taskRelationJson process task relation json |
|
* @param taskDefinitionJson taskDefinitionJson |
|
* @param processInstanceId process instance id |
|
* @param scheduleTime schedule time |
|
* @param syncDefine sync define |
|
* @param globalParams global params |
|
* @param locations locations for nodes |
|
* @param timeout timeout |
|
* @return update result code |
|
*/ |
|
@Transactional |
|
@Override |
|
public Map<String, Object> updateProcessInstance(User loginUser, long projectCode, Integer processInstanceId, |
|
String taskRelationJson, |
|
String taskDefinitionJson, String scheduleTime, Boolean syncDefine, |
|
String globalParams, |
|
String locations, int timeout) { |
|
// check user access for project |
|
projectService.checkProjectAndAuthThrowException(loginUser, projectCode, |
|
ApiFuncIdentificationConstant.INSTANCE_UPDATE); |
|
Map<String, Object> result = new HashMap<>(); |
|
// check process instance exists |
|
ProcessInstance processInstance = processService.findProcessInstanceDetailById(processInstanceId) |
|
.orElseThrow(() -> new ServiceException(PROCESS_INSTANCE_NOT_EXIST, processInstanceId)); |
|
// check process instance exists in project |
|
ProcessDefinition processDefinition0 = |
|
processDefineMapper.queryByCode(processInstance.getProcessDefinitionCode()); |
|
if (processDefinition0 != null && projectCode != processDefinition0.getProjectCode()) { |
|
log.error("Process definition does not exist, projectCode:{}, processDefinitionCode:{}.", projectCode, |
|
processInstance.getProcessDefinitionCode()); |
|
putMsg(result, PROCESS_INSTANCE_NOT_EXIST, processInstanceId); |
|
return result; |
|
} |
|
// check process instance status |
|
if (!processInstance.getState().isFinished()) { |
|
log.warn("Process Instance state is {} so can not update process instance, processInstanceId:{}.", |
|
processInstance.getState().getDesc(), processInstanceId); |
|
putMsg(result, PROCESS_INSTANCE_STATE_OPERATION_ERROR, |
|
processInstance.getName(), processInstance.getState().toString(), "update"); |
|
return result; |
|
} |
|
|
|
// |
|
Map<String, String> commandParamMap = JSONUtils.toMap(processInstance.getCommandParam()); |
|
String timezoneId = null; |
|
if (commandParamMap == null || StringUtils.isBlank(commandParamMap.get(Constants.SCHEDULE_TIMEZONE))) { |
|
timezoneId = loginUser.getTimeZone(); |
|
} else { |
|
timezoneId = commandParamMap.get(Constants.SCHEDULE_TIMEZONE); |
|
} |
|
|
|
setProcessInstance(processInstance, scheduleTime, globalParams, timeout, timezoneId); |
|
List<TaskDefinitionLog> taskDefinitionLogs = JSONUtils.toList(taskDefinitionJson, TaskDefinitionLog.class); |
|
if (taskDefinitionLogs.isEmpty()) { |
|
log.warn("Parameter taskDefinitionJson is empty"); |
|
putMsg(result, Status.DATA_IS_NOT_VALID, taskDefinitionJson); |
|
return result; |
|
} |
|
for (TaskDefinitionLog taskDefinitionLog : taskDefinitionLogs) { |
|
if (!taskPluginManager.checkTaskParameters(ParametersNode.builder() |
|
.taskType(taskDefinitionLog.getTaskType()) |
|
.taskParams(taskDefinitionLog.getTaskParams()) |
|
.dependence(taskDefinitionLog.getDependence()) |
|
.build())) { |
|
log.error("Task parameters are invalid, taskDefinitionName:{}.", taskDefinitionLog.getName()); |
|
putMsg(result, Status.PROCESS_NODE_S_PARAMETER_INVALID, taskDefinitionLog.getName()); |
|
return result; |
|
} |
|
} |
|
int saveTaskResult = processService.saveTaskDefine(loginUser, projectCode, taskDefinitionLogs, syncDefine); |
|
if (saveTaskResult == Constants.DEFINITION_FAILURE) { |
|
log.error("Update task definition error, projectCode:{}, processInstanceId:{}", projectCode, |
|
processInstanceId); |
|
putMsg(result, Status.UPDATE_TASK_DEFINITION_ERROR); |
|
throw new ServiceException(Status.UPDATE_TASK_DEFINITION_ERROR); |
|
} |
|
ProcessDefinition processDefinition = |
|
processDefineMapper.queryByCode(processInstance.getProcessDefinitionCode()); |
|
List<ProcessTaskRelationLog> taskRelationList = |
|
JSONUtils.toList(taskRelationJson, ProcessTaskRelationLog.class); |
|
// check workflow json is valid |
|
result = processDefinitionService.checkProcessNodeList(taskRelationJson, taskDefinitionLogs); |
|
if (result.get(Constants.STATUS) != Status.SUCCESS) { |
|
return result; |
|
} |
|
|
|
processDefinition.set(projectCode, processDefinition.getName(), processDefinition.getDescription(), |
|
globalParams, locations, timeout); |
|
processDefinition.setUpdateTime(new Date()); |
|
int insertVersion = processService.saveProcessDefine(loginUser, processDefinition, syncDefine, Boolean.FALSE); |
|
if (insertVersion == 0) { |
|
log.error("Update process definition error, projectCode:{}, processDefinitionName:{}.", projectCode, |
|
processDefinition.getName()); |
|
putMsg(result, Status.UPDATE_PROCESS_DEFINITION_ERROR); |
|
throw new ServiceException(Status.UPDATE_PROCESS_DEFINITION_ERROR); |
|
} else |
|
log.info("Update process definition complete, projectCode:{}, processDefinitionName:{}.", projectCode, |
|
processDefinition.getName()); |
|
int insertResult = processService.saveTaskRelation(loginUser, processDefinition.getProjectCode(), |
|
processDefinition.getCode(), insertVersion, taskRelationList, taskDefinitionLogs, syncDefine); |
|
if (insertResult == Constants.EXIT_CODE_SUCCESS) { |
|
log.info( |
|
"Update task relations complete, projectCode:{}, processDefinitionCode:{}, processDefinitionVersion:{}.", |
|
projectCode, processDefinition.getCode(), insertVersion); |
|
putMsg(result, Status.SUCCESS); |
|
result.put(Constants.DATA_LIST, processDefinition); |
|
} else { |
|
log.info( |
|
"Update task relations error, projectCode:{}, processDefinitionCode:{}, processDefinitionVersion:{}.", |
|
projectCode, processDefinition.getCode(), insertVersion); |
|
putMsg(result, Status.UPDATE_PROCESS_DEFINITION_ERROR); |
|
throw new ServiceException(Status.UPDATE_PROCESS_DEFINITION_ERROR); |
|
} |
|
processInstance.setProcessDefinitionVersion(insertVersion); |
|
boolean update = processInstanceDao.updateById(processInstance); |
|
if (!update) { |
|
log.error( |
|
"Update process instance version error, projectCode:{}, processDefinitionCode:{}, processDefinitionVersion:{}", |
|
projectCode, processDefinition.getCode(), insertVersion); |
|
putMsg(result, Status.UPDATE_PROCESS_INSTANCE_ERROR); |
|
throw new ServiceException(Status.UPDATE_PROCESS_INSTANCE_ERROR); |
|
} |
|
log.info( |
|
"Update process instance complete, projectCode:{}, processDefinitionCode:{}, processDefinitionVersion:{}, processInstanceId:{}", |
|
projectCode, processDefinition.getCode(), insertVersion, processInstanceId); |
|
putMsg(result, Status.SUCCESS); |
|
return result; |
|
} |
|
|
|
/** |
|
* update process instance attributes |
|
*/ |
|
private void setProcessInstance(ProcessInstance processInstance, String scheduleTime, |
|
String globalParams, int timeout, String timezone) { |
|
Date schedule = processInstance.getScheduleTime(); |
|
if (scheduleTime != null) { |
|
schedule = DateUtils.stringToDate(scheduleTime); |
|
} |
|
processInstance.setScheduleTime(schedule); |
|
List<Property> globalParamList = JSONUtils.toList(globalParams, Property.class); |
|
Map<String, String> globalParamMap = |
|
globalParamList.stream().collect(Collectors.toMap(Property::getProp, Property::getValue)); |
|
globalParams = curingGlobalParamsService.curingGlobalParams(processInstance.getId(), globalParamMap, |
|
globalParamList, processInstance.getCmdTypeIfComplement(), schedule, timezone); |
|
processInstance.setTimeout(timeout); |
|
processInstance.setGlobalParams(globalParams); |
|
} |
|
|
|
/** |
|
* query parent process instance detail info by sub process instance id |
|
* |
|
* @param loginUser login user |
|
* @param projectCode project code |
|
* @param subId sub process id |
|
* @return parent instance detail |
|
*/ |
|
@Override |
|
public Map<String, Object> queryParentInstanceBySubId(User loginUser, long projectCode, Integer subId) { |
|
Project project = projectMapper.queryByCode(projectCode); |
|
// check user access for project |
|
Map<String, Object> result = |
|
projectService.checkProjectAndAuth(loginUser, project, projectCode, |
|
ApiFuncIdentificationConstant.WORKFLOW_INSTANCE); |
|
if (result.get(Constants.STATUS) != Status.SUCCESS) { |
|
return result; |
|
} |
|
|
|
ProcessInstance subInstance = processService.findProcessInstanceDetailById(subId) |
|
.orElseThrow(() -> new ServiceException(PROCESS_INSTANCE_NOT_EXIST, subId)); |
|
if (subInstance.getIsSubProcess() == Flag.NO) { |
|
log.warn( |
|
"Process instance is not sub process instance type, processInstanceId:{}, processInstanceName:{}.", |
|
subId, subInstance.getName()); |
|
putMsg(result, Status.PROCESS_INSTANCE_NOT_SUB_PROCESS_INSTANCE, subInstance.getName()); |
|
return result; |
|
} |
|
|
|
ProcessInstance parentWorkflowInstance = processService.findParentProcessInstance(subId); |
|
if (parentWorkflowInstance == null) { |
|
log.error("Parent process instance does not exist, projectCode:{}, subProcessInstanceId:{}.", |
|
projectCode, subId); |
|
putMsg(result, Status.SUB_PROCESS_INSTANCE_NOT_EXIST); |
|
return result; |
|
} |
|
Map<String, Object> dataMap = new HashMap<>(); |
|
dataMap.put(Constants.PARENT_WORKFLOW_INSTANCE, parentWorkflowInstance.getId()); |
|
result.put(DATA_LIST, dataMap); |
|
putMsg(result, Status.SUCCESS); |
|
return result; |
|
} |
|
|
|
/** |
|
* delete process instance by id, at the same time,delete task instance and their mapping relation data |
|
* |
|
* @param loginUser login user |
|
* @param processInstanceId process instance id |
|
* @return delete result code |
|
*/ |
|
@Override |
|
@Transactional |
|
public void deleteProcessInstanceById(User loginUser, Integer processInstanceId) { |
|
ProcessInstance processInstance = processService.findProcessInstanceDetailById(processInstanceId) |
|
.orElseThrow(() -> new ServiceException(PROCESS_INSTANCE_NOT_EXIST, processInstanceId)); |
|
ProcessDefinition processDefinition = processDefinitionLogMapper.queryByDefinitionCodeAndVersion( |
|
processInstance.getProcessDefinitionCode(), processInstance.getProcessDefinitionVersion()); |
|
|
|
Project project = projectMapper.queryByCode(processDefinition.getProjectCode()); |
|
// check user access for project |
|
projectService.checkProjectAndAuthThrowException(loginUser, project, |
|
ApiFuncIdentificationConstant.INSTANCE_DELETE); |
|
// check process instance status |
|
if (!processInstance.getState().isFinished()) { |
|
log.warn("Process Instance state is {} so can not delete process instance, processInstanceId:{}.", |
|
processInstance.getState().getDesc(), processInstanceId); |
|
throw new ServiceException(PROCESS_INSTANCE_STATE_OPERATION_ERROR, processInstance.getName(), |
|
processInstance.getState(), "delete"); |
|
} |
|
deleteProcessInstanceById(processInstanceId); |
|
} |
|
|
|
/** |
|
* view process instance variables |
|
* |
|
* @param projectCode project code |
|
* @param processInstanceId process instance id |
|
* @return variables data |
|
*/ |
|
@Override |
|
public Map<String, Object> viewVariables(long projectCode, Integer processInstanceId) { |
|
Map<String, Object> result = new HashMap<>(); |
|
|
|
ProcessInstance processInstance = processInstanceMapper.queryDetailById(processInstanceId); |
|
|
|
if (processInstance == null) { |
|
log.error("Process instance does not exist, projectCode:{}, processInstanceId:{}.", projectCode, |
|
processInstanceId); |
|
putMsg(result, Status.PROCESS_INSTANCE_NOT_EXIST, processInstanceId); |
|
return result; |
|
} |
|
|
|
ProcessDefinition processDefinition = |
|
processDefineMapper.queryByCode(processInstance.getProcessDefinitionCode()); |
|
if (processDefinition != null && projectCode != processDefinition.getProjectCode()) { |
|
log.error("Process definition does not exist, projectCode:{}, processDefinitionCode:{}.", projectCode, |
|
processInstance.getProcessDefinitionCode()); |
|
putMsg(result, PROCESS_INSTANCE_NOT_EXIST, processInstanceId); |
|
return result; |
|
} |
|
|
|
Map<String, String> commandParam = JSONUtils.toMap(processInstance.getCommandParam()); |
|
String timezone = null; |
|
if (commandParam != null) { |
|
timezone = commandParam.get(Constants.SCHEDULE_TIMEZONE); |
|
} |
|
Map<String, String> timeParams = BusinessTimeUtils |
|
.getBusinessTime(processInstance.getCmdTypeIfComplement(), |
|
processInstance.getScheduleTime(), timezone); |
|
String userDefinedParams = processInstance.getGlobalParams(); |
|
// global params |
|
List<Property> globalParams = new ArrayList<>(); |
|
|
|
// global param string |
|
String globalParamStr = |
|
ParameterUtils.convertParameterPlaceholders(JSONUtils.toJsonString(globalParams), timeParams); |
|
globalParams = JSONUtils.toList(globalParamStr, Property.class); |
|
for (Property property : globalParams) { |
|
timeParams.put(property.getProp(), property.getValue()); |
|
} |
|
|
|
if (userDefinedParams != null && userDefinedParams.length() > 0) { |
|
globalParams = JSONUtils.toList(userDefinedParams, Property.class); |
|
} |
|
|
|
Map<String, Map<String, Object>> localUserDefParams = getLocalParams(processInstance, timeParams); |
|
|
|
Map<String, Object> resultMap = new HashMap<>(); |
|
|
|
resultMap.put(GLOBAL_PARAMS, globalParams); |
|
resultMap.put(LOCAL_PARAMS, localUserDefParams); |
|
|
|
result.put(DATA_LIST, resultMap); |
|
putMsg(result, Status.SUCCESS); |
|
return result; |
|
} |
|
|
|
/** |
|
* get local params |
|
*/ |
|
private Map<String, Map<String, Object>> getLocalParams(ProcessInstance processInstance, |
|
Map<String, String> timeParams) { |
|
Map<String, Map<String, Object>> localUserDefParams = new HashMap<>(); |
|
List<TaskInstance> taskInstanceList = |
|
taskInstanceMapper.findValidTaskListByProcessId(processInstance.getId(), Flag.YES, |
|
processInstance.getTestFlag()); |
|
for (TaskInstance taskInstance : taskInstanceList) { |
|
TaskDefinitionLog taskDefinitionLog = taskDefinitionLogMapper.queryByDefinitionCodeAndVersion( |
|
taskInstance.getTaskCode(), taskInstance.getTaskDefinitionVersion()); |
|
|
|
String localParams = JSONUtils.getNodeString(taskDefinitionLog.getTaskParams(), LOCAL_PARAMS); |
|
if (!StringUtils.isEmpty(localParams)) { |
|
localParams = ParameterUtils.convertParameterPlaceholders(localParams, timeParams); |
|
List<Property> localParamsList = JSONUtils.toList(localParams, Property.class); |
|
|
|
Map<String, Object> localParamsMap = new HashMap<>(); |
|
localParamsMap.put(TASK_TYPE, taskDefinitionLog.getTaskType()); |
|
localParamsMap.put(LOCAL_PARAMS_LIST, localParamsList); |
|
if (CollectionUtils.isNotEmpty(localParamsList)) { |
|
localUserDefParams.put(taskDefinitionLog.getName(), localParamsMap); |
|
} |
|
} |
|
} |
|
return localUserDefParams; |
|
} |
|
|
|
/** |
|
* encapsulation gantt structure |
|
* |
|
* @param projectCode project code |
|
* @param processInstanceId process instance id |
|
* @return gantt tree data |
|
* @throws Exception exception when json parse |
|
*/ |
|
@Override |
|
public Map<String, Object> viewGantt(long projectCode, Integer processInstanceId) throws Exception { |
|
Map<String, Object> result = new HashMap<>(); |
|
ProcessInstance processInstance = processInstanceMapper.queryDetailById(processInstanceId); |
|
|
|
if (processInstance == null) { |
|
log.error("Process instance does not exist, projectCode:{}, processInstanceId:{}.", projectCode, |
|
processInstanceId); |
|
putMsg(result, Status.PROCESS_INSTANCE_NOT_EXIST, processInstanceId); |
|
return result; |
|
} |
|
|
|
ProcessDefinition processDefinition = processDefinitionLogMapper.queryByDefinitionCodeAndVersion( |
|
processInstance.getProcessDefinitionCode(), |
|
processInstance.getProcessDefinitionVersion()); |
|
if (processDefinition == null || projectCode != processDefinition.getProjectCode()) { |
|
log.error("Process definition does not exist, projectCode:{}, processDefinitionCode:{}.", projectCode, |
|
processInstance.getProcessDefinitionCode()); |
|
putMsg(result, PROCESS_INSTANCE_NOT_EXIST, processInstanceId); |
|
return result; |
|
} |
|
GanttDto ganttDto = new GanttDto(); |
|
DAG<Long, TaskNode, TaskNodeRelation> dag = processService.genDagGraph(processDefinition); |
|
// topological sort |
|
List<Long> nodeList = dag.topologicalSort(); |
|
|
|
ganttDto.setTaskNames(nodeList); |
|
|
|
List<Task> taskList = new ArrayList<>(); |
|
if (CollectionUtils.isNotEmpty(nodeList)) { |
|
List<TaskInstance> taskInstances = taskInstanceMapper.queryByProcessInstanceIdsAndTaskCodes( |
|
Collections.singletonList(processInstanceId), nodeList); |
|
for (Long node : nodeList) { |
|
TaskInstance taskInstance = null; |
|
for (TaskInstance instance : taskInstances) { |
|
if (instance.getProcessInstanceId() == processInstanceId && instance.getTaskCode() == node) { |
|
taskInstance = instance; |
|
break; |
|
} |
|
} |
|
if (taskInstance == null) { |
|
continue; |
|
} |
|
Date startTime = taskInstance.getStartTime() == null ? new Date() : taskInstance.getStartTime(); |
|
Date endTime = taskInstance.getEndTime() == null ? new Date() : taskInstance.getEndTime(); |
|
Task task = new Task(); |
|
task.setTaskName(taskInstance.getName()); |
|
task.getStartDate().add(startTime.getTime()); |
|
task.getEndDate().add(endTime.getTime()); |
|
task.setIsoStart(startTime); |
|
task.setIsoEnd(endTime); |
|
task.setStatus(taskInstance.getState().name()); |
|
task.setExecutionDate(taskInstance.getStartTime()); |
|
task.setDuration(DateUtils.format2Readable(endTime.getTime() - startTime.getTime())); |
|
taskList.add(task); |
|
} |
|
} |
|
ganttDto.setTasks(taskList); |
|
|
|
result.put(DATA_LIST, ganttDto); |
|
putMsg(result, Status.SUCCESS); |
|
return result; |
|
} |
|
|
|
/** |
|
* query process instance by processDefinitionCode and stateArray |
|
* |
|
* @param processDefinitionCode processDefinitionCode |
|
* @param states states array |
|
* @return process instance list |
|
*/ |
|
@Override |
|
public List<ProcessInstance> queryByProcessDefineCodeAndStatus(Long processDefinitionCode, int[] states) { |
|
return processInstanceMapper.queryByProcessDefineCodeAndStatus(processDefinitionCode, states); |
|
} |
|
|
|
@Override |
|
public List<ProcessInstance> queryByWorkflowCodeVersionStatus(Long workflowDefinitionCode, |
|
int workflowDefinitionVersion, int[] states) { |
|
return processInstanceDao.queryByWorkflowCodeVersionStatus(workflowDefinitionCode, workflowDefinitionVersion, |
|
states); |
|
} |
|
|
|
/** |
|
* query process instance by processDefinitionCode |
|
* |
|
* @param processDefinitionCode processDefinitionCode |
|
* @param size size |
|
* @return process instance list |
|
*/ |
|
@Override |
|
public List<ProcessInstance> queryByProcessDefineCode(Long processDefinitionCode, int size) { |
|
return processInstanceMapper.queryByProcessDefineCode(processDefinitionCode, size); |
|
} |
|
|
|
/** |
|
* query process instance list bt trigger code |
|
* |
|
* @param loginUser |
|
* @param projectCode |
|
* @param triggerCode |
|
* @return |
|
*/ |
|
@Override |
|
public Map<String, Object> queryByTriggerCode(User loginUser, long projectCode, Long triggerCode) { |
|
|
|
Project project = projectMapper.queryByCode(projectCode); |
|
// check user access for project |
|
Map<String, Object> result = |
|
projectService.checkProjectAndAuth(loginUser, project, projectCode, WORKFLOW_INSTANCE); |
|
if (result.get(Constants.STATUS) != Status.SUCCESS || triggerCode == null) { |
|
return result; |
|
} |
|
|
|
List<ProcessInstance> processInstances = processInstanceMapper.queryByTriggerCode( |
|
triggerCode); |
|
result.put(DATA_LIST, processInstances); |
|
putMsg(result, Status.SUCCESS); |
|
return result; |
|
} |
|
|
|
@Override |
|
public void deleteProcessInstanceByWorkflowDefinitionCode(long workflowDefinitionCode) { |
|
while (true) { |
|
List<ProcessInstance> processInstances = |
|
processInstanceMapper.queryByProcessDefineCode(workflowDefinitionCode, 100); |
|
if (CollectionUtils.isEmpty(processInstances)) { |
|
break; |
|
} |
|
log.info("Begin to delete workflow instance, workflow definition code: {}", workflowDefinitionCode); |
|
for (ProcessInstance processInstance : processInstances) { |
|
if (!processInstance.getState().isFinished()) { |
|
log.warn("Workflow instance is not finished cannot delete, process instance id:{}", |
|
processInstance.getId()); |
|
throw new ServiceException(PROCESS_INSTANCE_STATE_OPERATION_ERROR, processInstance.getName(), |
|
processInstance.getState(), "delete"); |
|
} |
|
deleteProcessInstanceById(processInstance.getId()); |
|
} |
|
log.info("Success delete workflow instance, workflow definition code: {}, size: {}", |
|
workflowDefinitionCode, processInstances.size()); |
|
} |
|
} |
|
|
|
@Override |
|
public void deleteProcessInstanceById(int workflowInstanceId) { |
|
// delete task instance |
|
taskInstanceService.deleteByWorkflowInstanceId(workflowInstanceId); |
|
// delete sub process instances |
|
deleteSubWorkflowInstanceIfNeeded(workflowInstanceId); |
|
// delete alert |
|
alertDao.deleteByWorkflowInstanceId(workflowInstanceId); |
|
// delete process instance |
|
processInstanceDao.deleteById(workflowInstanceId); |
|
} |
|
|
|
private void deleteSubWorkflowInstanceIfNeeded(int workflowInstanceId) { |
|
List<Integer> subWorkflowInstanceIds = processInstanceMapDao.querySubWorkflowInstanceIds(workflowInstanceId); |
|
if (org.apache.commons.collections4.CollectionUtils.isEmpty(subWorkflowInstanceIds)) { |
|
return; |
|
} |
|
for (Integer subWorkflowInstanceId : subWorkflowInstanceIds) { |
|
deleteProcessInstanceById(subWorkflowInstanceId); |
|
} |
|
processInstanceMapDao.deleteByParentId(workflowInstanceId); |
|
} |
|
}
|
|
|