feat - 项目启动完成后,提供 web 服务前,恢复动态加签逻辑

This commit is contained in:
wangli 2025-10-20 11:15:41 +08:00
parent 4d1193d333
commit 1e4d9e2ea9
5 changed files with 112 additions and 8 deletions

View File

@ -27,6 +27,7 @@ import cn.axzo.workflow.core.engine.job.exception.handle.CustomAsyncJobLogClearT
import cn.axzo.workflow.core.engine.job.exception.handle.CustomAsyncRunnableExceptionExceptionHandler;
import cn.axzo.workflow.core.engine.persistence.CustomMybatisHistoricProcessInstanceDataManager;
import cn.axzo.workflow.core.service.BpmnProcessActivityService;
import cn.axzo.workflow.core.service.ExtAxDynamicSignRecordService;
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
import cn.azxo.framework.common.constatns.Constants;
import cn.hutool.core.util.ReflectUtil;
@ -83,6 +84,7 @@ public class FlowableConfiguration {
ObjectProvider<FlowableEventListener> listeners,
CustomActivityBehaviorFactory customActivityBehaviorFactory,
ExtAxHiTaskInstService extAxHiTaskInstService,
ExtAxDynamicSignRecordService extAxDynamicSignRecordService,
BpmnProcessActivityService bpmnProcessActivityService,
List<JobProcessor> jobProcessors,
NacosServiceManager nacosServiceManager,
@ -110,12 +112,11 @@ public class FlowableConfiguration {
configuration.addCustomJobHandler(new AsyncApproveTaskJobHandler());
configuration.addCustomJobHandler(new AsyncBackTaskJobHandler());
configuration.addCustomJobHandler(new AsyncCancelProcessInstanceJobHandler(extAxHiTaskInstService));
configuration.addCustomJobHandler(new AsyncCountersignUserTaskJobHandler(extAxHiTaskInstService));
configuration.addCustomJobHandler(new AsyncCountersignUserTaskJobHandler(extAxHiTaskInstService, extAxDynamicSignRecordService));
configuration.addCustomJobHandler(new AsyncExtTaskInstJobHandler(extAxHiTaskInstService));
configuration.addCustomJobHandler(new AsyncRejectTaskJobHandler(extAxHiTaskInstService));
configuration.addCustomJobHandler(new AsyncTransferUserTaskJobHandler());
configuration.addCustomJobHandler(new AsyncTermNodeAlterJobHandler(refreshProperties));
configuration.addCustomJobHandler(new AsyncCountersignUserTaskJobHandler(extAxHiTaskInstService));
configuration.addCustomJobHandler(new AsyncActivityLeaveJobHandler(bpmnProcessActivityService));
configuration.addCustomJobHandler(new AsyncActivityCallbackJobHandler());
configuration.addCustomJobHandler(new AsyncApproveTaskWithFormJobHandler());

View File

@ -8,6 +8,8 @@ import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.engine.cmd.helper.CustomBpmnModelHelper;
import cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper;
import cn.axzo.workflow.core.engine.model.AddComment;
import cn.axzo.workflow.core.repository.entity.ExtAxDynamicSignRecord;
import cn.axzo.workflow.core.service.ExtAxDynamicSignRecordService;
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
@ -45,6 +47,7 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.COUNTERSIGN_ASSIGNE
import static cn.axzo.workflow.common.constant.BpmnConstants.FORWARD_ACTIVITY_FRAGMENT;
import static cn.axzo.workflow.common.constant.BpmnConstants.FORWARD_COUNTERSIGN_COUNT;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT;
import static cn.axzo.workflow.common.enums.BpmnCountersignTypeEnum.FORWARD_COUNTERSIGN;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.COUNTERSIGN;
import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getCategoryVersion;
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.addMultiTask;
@ -75,11 +78,14 @@ public class CustomCountersignUserTaskCmd extends AbstractCommand<Void> implemen
private final List<AttachmentDTO> attachmentList;
private final List<BpmnTaskDelegateAssigner> targetTaskAssigneeList;
private final ExtAxHiTaskInstService extAxHiTaskInstService;
private final ExtAxDynamicSignRecordService extAxDynamicSignRecordService;
public CustomCountersignUserTaskCmd(BpmnCountersignTypeEnum countersignType, String originTaskId,
BpmnTaskDelegateAssigner originTaskAssignee, String advice,
List<AttachmentDTO> attachmentList,
List<BpmnTaskDelegateAssigner> targetTaskAssigneeList, ExtAxHiTaskInstService extAxHiTaskInstService) {
List<BpmnTaskDelegateAssigner> targetTaskAssigneeList,
ExtAxHiTaskInstService extAxHiTaskInstService,
ExtAxDynamicSignRecordService extAxDynamicSignRecordService) {
this.countersignType = countersignType;
this.originTaskId = originTaskId;
this.originTaskAssignee = originTaskAssignee;
@ -87,6 +93,7 @@ public class CustomCountersignUserTaskCmd extends AbstractCommand<Void> implemen
this.attachmentList = attachmentList;
this.targetTaskAssigneeList = targetTaskAssigneeList;
this.extAxHiTaskInstService = extAxHiTaskInstService;
this.extAxDynamicSignRecordService = extAxDynamicSignRecordService;
}
@Override
@ -191,6 +198,15 @@ public class CustomCountersignUserTaskCmd extends AbstractCommand<Void> implemen
// 重新连接顺序流 (Sequence Flow)
CustomBpmnModelHelper.rewireSequenceFlows(process, originalUserTask, newUserTask);
ExtAxDynamicSignRecord entity = new ExtAxDynamicSignRecord();
entity.setProcessInstanceId(processInstance.getProcessInstanceId());
entity.setProcessDefinitionId(processInstance.getProcessDefinitionId());
entity.setOriginalActivityId(originalUserTask.getId());
entity.setTargetActivityId(newUserTask.getId());
entity.setCounterSignType(FORWARD_COUNTERSIGN.getType());
entity.setAssignerList(valuTargetAssigneeList);
extAxDynamicSignRecordService.saveOrUpdate(entity);
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveActivityIdTo(task.getTaskDefinitionKey(), newUserTask.getId())

View File

@ -3,6 +3,7 @@ package cn.axzo.workflow.core.engine.job;
import cn.axzo.workflow.common.enums.BpmnCountersignTypeEnum;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO;
import cn.axzo.workflow.core.engine.cmd.CustomCountersignUserTaskCmd;
import cn.axzo.workflow.core.service.ExtAxDynamicSignRecordService;
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
@ -19,9 +20,12 @@ public class AsyncCountersignUserTaskJobHandler extends AbstractJobHandler imple
public static final String TYPE = "async-countersign-task";
private final ExtAxHiTaskInstService extAxHiTaskInstService;
private final ExtAxDynamicSignRecordService extAxDynamicSignRecordService;
public AsyncCountersignUserTaskJobHandler(ExtAxHiTaskInstService extAxHiTaskInstService) {
public AsyncCountersignUserTaskJobHandler(ExtAxHiTaskInstService extAxHiTaskInstService,
ExtAxDynamicSignRecordService extAxDynamicSignRecordService) {
this.extAxHiTaskInstService = extAxHiTaskInstService;
this.extAxDynamicSignRecordService = extAxDynamicSignRecordService;
}
@Override
@ -42,6 +46,7 @@ public class AsyncCountersignUserTaskJobHandler extends AbstractJobHandler imple
dto.getAdvice(),
dto.getAttachmentList(),
dto.getTargetAssignerList(),
extAxHiTaskInstService));
extAxHiTaskInstService,
extAxDynamicSignRecordService));
}
}

View File

@ -32,9 +32,14 @@ public class ExtAxDynamicSignRecord extends BaseEntity<ExtAxDynamicSignRecord> {
*/
private String processDefinitionId;
/**
* 加签次数
* 加签原节点
*/
private Integer counterSignCount;
private String originalActivityId;
/**
* 加签目标节点
*/
private String targetActivityId;
/**
* 加签类型前加签/后加签
* {@link BpmnCountersignTypeEnum}

View File

@ -1,12 +1,32 @@
package cn.axzo.workflow.server.initializer;
import cn.axzo.workflow.common.enums.BpmnFlowNodeMode;
import cn.axzo.workflow.core.engine.cmd.helper.CustomBpmnModelHelper;
import cn.axzo.workflow.core.repository.entity.ExtAxDynamicSignRecord;
import cn.axzo.workflow.core.service.ExtAxDynamicSignRecordService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.impl.persistence.deploy.DeploymentManager;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.springframework.context.SmartLifecycle;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static cn.axzo.workflow.common.constant.BpmnConstants.AND_SIGN_EXPRESSION;
import static cn.axzo.workflow.common.enums.BpmnCountersignTypeEnum.BACK_COUNTERSIGN;
import static cn.axzo.workflow.common.enums.BpmnCountersignTypeEnum.FORWARD_COUNTERSIGN;
/**
* 在框架提供 Web 服务前恢复动态前后加签的流程实例的内存中的模型
@ -18,10 +38,13 @@ import java.util.List;
@Component
public class RecoverDynamicCounterSignProcess implements SmartLifecycle {
private final ExtAxDynamicSignRecordService extAxDynamicSignRecordService;
private final SpringProcessEngineConfiguration springProcessEngineConfiguration;
private boolean isRunning = false;
public RecoverDynamicCounterSignProcess(ExtAxDynamicSignRecordService extAxDynamicSignRecordService) {
public RecoverDynamicCounterSignProcess(ExtAxDynamicSignRecordService extAxDynamicSignRecordService,
SpringProcessEngineConfiguration springProcessEngineConfiguration) {
this.extAxDynamicSignRecordService = extAxDynamicSignRecordService;
this.springProcessEngineConfiguration = springProcessEngineConfiguration;
}
@ -29,7 +52,61 @@ public class RecoverDynamicCounterSignProcess implements SmartLifecycle {
public void start() {
// TODO 恢复动态会签中的流程实例
log.info("executing before web server start");
// 查询有过加签的审批实例
List<ExtAxDynamicSignRecord> list = extAxDynamicSignRecordService.list();
if (CollectionUtils.isEmpty(list)) {
return;
}
RuntimeService runtimeService = springProcessEngineConfiguration.getRuntimeService();
// 获取还在审批中的实例
Set<String> processInstanceIds = list.stream().map(ExtAxDynamicSignRecord::getProcessInstanceId).collect(Collectors.toSet());
Set<String> runningProcessIds = runtimeService.createProcessInstanceQuery()
.processInstanceIds(processInstanceIds)
.active()
.list().stream().map(ProcessInstance::getProcessInstanceId).collect(Collectors.toSet());
if (CollectionUtils.isEmpty(runningProcessIds)) {
return;
}
Map<String, List<ExtAxDynamicSignRecord>> grouped = list.stream()
.collect(Collectors.groupingBy(
ExtAxDynamicSignRecord::getProcessInstanceId,
Collectors.collectingAndThen(
Collectors.toList(),
l -> {
l.sort(Comparator.comparing(
ExtAxDynamicSignRecord::getCreateAt,
Comparator.nullsFirst(Comparator.naturalOrder())
));
return l;
}
)
));
RepositoryService repositoryService = springProcessEngineConfiguration.getRepositoryService();
DeploymentManager deploymentManager = springProcessEngineConfiguration.getDeploymentManager();
grouped.forEach((k, v) -> {
if (runningProcessIds.contains(k)) {
log.info("recover dynamic counter sign process instance id: {}", k);
ProcessDefinition processDefinitionEntity = deploymentManager.findDeployedProcessDefinitionById(v.get(0).getProcessDefinitionId());
Process process = deploymentManager.resolveProcessDefinition(processDefinitionEntity).getProcess();
v.forEach(sign -> {
if (Objects.equals(sign.getCounterSignType(), FORWARD_COUNTERSIGN.getType())) {
UserTask originalUserTask = (UserTask) process.getFlowElement(sign.getOriginalActivityId());
BpmnFlowNodeMode nodeMode = Objects.equals(originalUserTask.getLoopCharacteristics().getCompletionCondition(), AND_SIGN_EXPRESSION) ? BpmnFlowNodeMode.AND : BpmnFlowNodeMode.OR;
// 创建前加签节点
UserTask newUserTask = CustomBpmnModelHelper.createUserTask(springProcessEngineConfiguration, originalUserTask, sign.getTargetActivityId(), nodeMode, sign.getAssignerList());
process.addFlowElement(newUserTask);
CustomBpmnModelHelper.rewireSequenceFlows(process, originalUserTask, newUserTask);
} else if (Objects.equals(sign.getCounterSignType(), BACK_COUNTERSIGN.getType())) {
}
});
}
});
isRunning = true;
}