feat(REQ-3383) - 优化机器人节点完成时,可能导致数据一致的问题

This commit is contained in:
wangli 2024-12-09 14:38:26 +08:00
parent 7b6b92242a
commit a26557305c
5 changed files with 85 additions and 11 deletions

View File

@ -0,0 +1,26 @@
package cn.axzo.workflow.common.model.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 简单的任务模型
*
* @author wangli
* @since 2024-12-09 14:30
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SimpleTaskDTO {
/**
* 流程实例 ID
*/
private String processInstanceId;
/**
* 任务 ID
*/
private String taskId;
}

View File

@ -1,18 +1,22 @@
package cn.axzo.workflow.core.engine.cmd; package cn.axzo.workflow.core.engine.cmd;
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum; import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
import cn.axzo.workflow.common.model.dto.SimpleTaskDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO; import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCompleteDTO; import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCompleteDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner; import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.common.exception.WorkflowEngineException; import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
import cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper; import cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper;
import cn.axzo.workflow.core.engine.tx.listener.RobotTaskTransactionListener;
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService; import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
import cn.axzo.workflow.core.service.ExtAxProcessLogService; import cn.axzo.workflow.core.service.ExtAxProcessLogService;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import org.flowable.common.engine.impl.cfg.TransactionState;
import org.flowable.common.engine.impl.identity.Authentication; import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.common.engine.impl.interceptor.CommandContext; import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.TaskService; import org.flowable.engine.TaskService;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.context.Context;
import org.flowable.engine.impl.util.CommandContextUtil; import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.api.Task; import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntity; import org.flowable.task.service.impl.persistence.entity.TaskEntity;
@ -20,6 +24,7 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -119,16 +124,18 @@ public class CustomCompleteDummyTaskCmd extends AbstractCommand<Void> implements
if (CollectionUtils.isEmpty(taskList)) { if (CollectionUtils.isEmpty(taskList)) {
return; return;
} }
List<SimpleTaskDTO> restoreTasks = new ArrayList<>();
taskList.stream().filter(i -> !Objects.equals(i.getTaskDefinitionKey(), NODE_ROBOT.getType())) taskList.stream().filter(i -> !Objects.equals(i.getTaskDefinitionKey(), NODE_ROBOT.getType()))
.filter(i -> Objects.equals(i.getAssignee(), HIDDEN_ASSIGNEE_ID)) .filter(i -> Objects.equals(i.getAssignee(), HIDDEN_ASSIGNEE_ID))
.forEach(i -> { .forEach(i -> {
taskService.setAssignee(i.getId(), i.getOwner()); taskService.setAssignee(i.getId(), i.getOwner());
taskService.setOwner(i.getId(), null); taskService.setOwner(i.getId(), null);
// TODO 待测试事务是否能在同一个 restoreTasks.add(new SimpleTaskDTO(i.getProcessInstanceId(), i.getId()));
extAxProcessLogService.restore(i.getProcessInstanceId(), i.getId());
}); });
Context.getTransactionContext().addTransactionListener(TransactionState.COMMITTED, new RobotTaskTransactionListener(restoreTasks, extAxProcessLogService));
} }
} }

View File

@ -0,0 +1,28 @@
package cn.axzo.workflow.core.engine.tx.listener;
import cn.axzo.workflow.common.model.dto.SimpleTaskDTO;
import cn.axzo.workflow.core.service.ExtAxProcessLogService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.impl.cfg.TransactionListener;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import java.util.List;
/**
* 恢复创建机器人节点时暂停的审批人任务
*
* @author wangli
* @since 2024-12-09 14:26
*/
@Slf4j
@AllArgsConstructor
public class RobotTaskTransactionListener implements TransactionListener {
private final List<SimpleTaskDTO> tasks;
private final ExtAxProcessLogService processLogService;
@Override
public void execute(CommandContext commandContext) {
processLogService.batchRestore(tasks);
}
}

View File

@ -1,5 +1,6 @@
package cn.axzo.workflow.core.service; package cn.axzo.workflow.core.service;
import cn.axzo.workflow.common.model.dto.SimpleTaskDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner; import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog; import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
@ -55,4 +56,6 @@ public interface ExtAxProcessLogService {
List<ExtAxProcessLog> genericQuery(ExtAxProcessLog query); List<ExtAxProcessLog> genericQuery(ExtAxProcessLog query);
void restore(String processInstanceId, String taskId); void restore(String processInstanceId, String taskId);
void batchRestore(List<SimpleTaskDTO> tasks);
} }

View File

@ -1,5 +1,6 @@
package cn.axzo.workflow.core.service.impl; package cn.axzo.workflow.core.service.impl;
import cn.axzo.workflow.common.model.dto.SimpleTaskDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner; import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog; import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
import cn.axzo.workflow.core.repository.mapper.ExtAxProcessLogMapper; import cn.axzo.workflow.core.repository.mapper.ExtAxProcessLogMapper;
@ -8,6 +9,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -59,7 +61,7 @@ public class ExtAxProcessLogServiceImpl implements ExtAxProcessLogService {
@Override @Override
public void updateAssignee(ExtAxProcessLog queryLog, BpmnTaskDelegateAssigner assignee, String operationDesc) { public void updateAssignee(ExtAxProcessLog queryLog, BpmnTaskDelegateAssigner assignee, String operationDesc) {
List<String> filterAssignee = Lists.newArrayList(NO_ASSIGNEE, HIDDEN_ASSIGNEE_ID, ROBOT_ASSIGNEE_ID, List<String> filterAssignee = Lists.newArrayList(NO_ASSIGNEE, HIDDEN_ASSIGNEE_ID, ROBOT_ASSIGNEE_ID,
DUMMY_ASSIGNEE_ID); DUMMY_ASSIGNEE_ID);
if (Objects.isNull(assignee) || filterAssignee.contains(assignee.buildAssigneeId())) { if (Objects.isNull(assignee) || filterAssignee.contains(assignee.buildAssigneeId())) {
return; return;
} }
@ -80,17 +82,25 @@ public class ExtAxProcessLogServiceImpl implements ExtAxProcessLogService {
@Override @Override
public void restore(String processInstanceId, String taskId) { public void restore(String processInstanceId, String taskId) {
extAxProcessLogMapper.restore(processInstanceId, taskId); batchRestore(Lists.newArrayList(new SimpleTaskDTO(processInstanceId, taskId)));
}
@Override
public void batchRestore(List<SimpleTaskDTO> tasks) {
if (CollectionUtils.isEmpty(tasks)) {
return;
}
tasks.forEach(task -> extAxProcessLogMapper.restore(task.getProcessInstanceId(), task.getTaskId()));
} }
LambdaQueryWrapper<ExtAxProcessLog> buildQueryWrapper(ExtAxProcessLog log) { LambdaQueryWrapper<ExtAxProcessLog> buildQueryWrapper(ExtAxProcessLog log) {
return new LambdaQueryWrapper<ExtAxProcessLog>() return new LambdaQueryWrapper<ExtAxProcessLog>()
.eq(Objects.nonNull(log.getId()), ExtAxProcessLog::getId, log.getId()) .eq(Objects.nonNull(log.getId()), ExtAxProcessLog::getId, log.getId())
.eq(StringUtils.hasText(log.getProcessInstanceId()), ExtAxProcessLog::getProcessInstanceId, log.getProcessInstanceId()) .eq(StringUtils.hasText(log.getProcessInstanceId()), ExtAxProcessLog::getProcessInstanceId, log.getProcessInstanceId())
.eq(StringUtils.hasText(log.getActivityId()), ExtAxProcessLog::getActivityId, log.getActivityId()) .eq(StringUtils.hasText(log.getActivityId()), ExtAxProcessLog::getActivityId, log.getActivityId())
.eq(StringUtils.hasText(log.getActivityName()), ExtAxProcessLog::getActivityName, log.getActivityName()) .eq(StringUtils.hasText(log.getActivityName()), ExtAxProcessLog::getActivityName, log.getActivityName())
.eq(StringUtils.hasText(log.getTaskId()), ExtAxProcessLog::getTaskId, log.getTaskId()) .eq(StringUtils.hasText(log.getTaskId()), ExtAxProcessLog::getTaskId, log.getTaskId())
.eq(StringUtils.hasText(log.getTenantId()), ExtAxProcessLog::getTenantId, log.getTenantId()) .eq(StringUtils.hasText(log.getTenantId()), ExtAxProcessLog::getTenantId, log.getTenantId())
.eq(ExtAxProcessLog::getIsDelete, log.getIsDelete()); .eq(ExtAxProcessLog::getIsDelete, log.getIsDelete());
} }
} }