diff --git a/pom.xml b/pom.xml
index b9cc62063..fe575363e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,6 +32,7 @@
2.0.0
2.5.0
0.0.1-SNAPSHOT
+ 2.0.1-SNAPSHOT
@@ -179,6 +180,11 @@
doc-api
${axzo-dependencies.version}
+
+ cn.axzo.infra
+ adapter
+ ${adapter.version}
+
diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/dto/TermNodeAddTimerJobDTO.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/dto/TermNodeAddTimerJobDTO.java
index c5e955d78..dd1790730 100644
--- a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/dto/TermNodeAddTimerJobDTO.java
+++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/dto/TermNodeAddTimerJobDTO.java
@@ -21,7 +21,9 @@ import java.io.Serializable;
@Builder
public class TermNodeAddTimerJobDTO implements Serializable {
private String processInstanceId;
+ private String processDefinitionId;
private String activityId;
+ private String activityName;
private Integer delayTime;
private String timeUnit;
}
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java
index b65829847..565d0dd4a 100644
--- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java
@@ -20,7 +20,6 @@ import cn.axzo.workflow.core.engine.job.AsyncExtTaskInstJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncRejectTaskJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncRemindTaskJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncResetApproversUserTaskJobHandler;
-import cn.axzo.workflow.core.engine.job.AsyncTermNodeAlterJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncTransferUserTaskJobHandler;
import cn.axzo.workflow.core.engine.job.NextActivityConfigCheckJobHandler;
import cn.axzo.workflow.core.engine.job.exception.handle.CustomAsyncJobLogClearTraceExceptionHandler;
@@ -114,7 +113,7 @@ public class FlowableConfiguration {
configuration.addCustomJobHandler(new AsyncExtTaskInstJobHandler(extAxHiTaskInstService));
configuration.addCustomJobHandler(new AsyncRejectTaskJobHandler(extAxHiTaskInstService));
configuration.addCustomJobHandler(new AsyncTransferUserTaskJobHandler());
- configuration.addCustomJobHandler(new AsyncTermNodeAlterJobHandler(refreshProperties));
+// configuration.addCustomJobHandler(new AsyncTermNodeAlterJobHandler(refreshProperties));
configuration.addCustomJobHandler(new AsyncCountersignUserTaskJobHandler(extAxHiTaskInstService));
configuration.addCustomJobHandler(new AsyncActivityLeaveJobHandler(bpmnProcessActivityService));
configuration.addCustomJobHandler(new AsyncActivityCallbackJobHandler());
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/SupportRefreshProperties.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/SupportRefreshProperties.java
index cfac43c61..e7b9974ef 100644
--- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/SupportRefreshProperties.java
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/SupportRefreshProperties.java
@@ -41,6 +41,16 @@ public class SupportRefreshProperties {
@Value(value = "${workflow.alter.enable:false}")
private Boolean alterEnable;
+ /**
+ * 是否全量业务 ID 都开启告警功能
+ */
+ @Value(value = "${workflow.alter.allDefinitionKey:false}")
+ private Boolean alterAllDefinitionKey;
+ /**
+ * 需要开启告警功能的业务 ID 列表
+ */
+ @Value(value = "${workflow.alter.definitionKeys:}")
+ private List alterDefinitionKeys;
/**
* 节点卡住多久才告警,单位分钟
*/
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomAddTimerJobCmd.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomAddTimerJobCmd.java
index 8e44f1ba2..99edf3998 100644
--- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomAddTimerJobCmd.java
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomAddTimerJobCmd.java
@@ -1,16 +1,13 @@
package cn.axzo.workflow.core.engine.cmd;
import cn.axzo.workflow.common.model.dto.TermNodeAddTimerJobDTO;
-import cn.axzo.workflow.core.engine.job.AsyncTermNodeAlterJobHandler;
+import cn.axzo.workflow.core.common.utils.SpringContextUtils;
+import cn.axzo.workflow.core.repository.entity.ExtAxNodeAlterJob;
+import cn.axzo.workflow.core.service.ExtAxNodeAlterJobService;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.impl.interceptor.CommandContext;
-import org.flowable.engine.ManagementService;
-import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
-import org.flowable.engine.impl.util.CommandContextUtil;
-import org.flowable.job.service.TimerJobService;
-import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
import java.io.Serializable;
import java.util.Date;
@@ -37,14 +34,11 @@ public class CustomAddTimerJobCmd extends AbstractCommand implements Seria
@Override
public Void executeInternal(CommandContext commandContext) {
log.info("CustomAddTimerJobCmd start. instanceId: {}, activityId: {}, delayTime: {}, timeUnit: {}", dto.getProcessInstanceId(), dto.getActivityId(), dto.getDelayTime(), dto.getTimeUnit());
- ProcessEngineConfigurationImpl processEngineConfiguration =
- CommandContextUtil.getProcessEngineConfiguration(commandContext);
- ManagementService managementService = processEngineConfiguration.getManagementService();
Date alterTime;
switch (dto.getTimeUnit()) {
case "M":
- alterTime = DateUtil.offsetDay(new Date(), dto.getDelayTime());
+ alterTime = DateUtil.offsetMinute(new Date(), dto.getDelayTime());
break;
case "H":
alterTime = DateUtil.offsetHour(new Date(), dto.getDelayTime());
@@ -54,20 +48,15 @@ public class CustomAddTimerJobCmd extends AbstractCommand implements Seria
break;
}
- managementService.executeCommand(context -> {
- TimerJobService timerJobService = CommandContextUtil.getTimerJobService();
- TimerJobEntity timerJobEntity = timerJobService.createTimerJob();
- timerJobEntity.setJobType("timer");
- timerJobEntity.setJobHandlerType(AsyncTermNodeAlterJobHandler.TYPE); // 这里填写你自定义的 JobHandler 类型
- timerJobEntity.setProcessInstanceId(dto.getProcessInstanceId());
- timerJobEntity.setExecutionId(null);
- timerJobEntity.setDuedate(alterTime); // 立即执行
- timerJobEntity.setRepeat(null); // 不重复
- timerJobEntity.setRetries(1);
- timerJobEntity.setJobHandlerConfiguration(dto.getActivityId()); // 可选,传递参数
- timerJobService.scheduleTimerJob(timerJobEntity);
- return null;
- });
+ ExtAxNodeAlterJobService service = SpringContextUtils.getBean(ExtAxNodeAlterJobService.class);
+ ExtAxNodeAlterJob job = new ExtAxNodeAlterJob();
+ job.setProcessInstanceId(dto.getProcessInstanceId());
+ job.setProcessDefinitionId(dto.getProcessDefinitionId());
+ job.setActivityId(dto.getActivityId());
+ job.setActivityName(dto.getActivityName());
+ job.setAlterTime(alterTime);
+ job.setException("");
+ service.save(job);
return null;
}
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomBizSpecifyAssigneeToTaskCmd.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomBizSpecifyAssigneeToTaskCmd.java
index 4446489b9..112ea35f6 100644
--- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomBizSpecifyAssigneeToTaskCmd.java
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomBizSpecifyAssigneeToTaskCmd.java
@@ -89,12 +89,13 @@ public class CustomBizSpecifyAssigneeToTaskCmd extends AbstractCommand
* @param assigners
*/
public static void validate(RuntimeService runtimeService, String executionId, Task task, List assigners) {
+ validTask(task, executionId);
+
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(task.getProcessDefinitionId());
boolean present = assigners.stream().anyMatch(assigner -> !StringUtils.hasText(assigner.getNodeId()));
if (present && getCategoryVersion(bpmnModel.getMainProcess()).orElse(0) > 0) {
throw new WorkflowEngineException(ASSIGNEE_NODE_ID_NOT_EXISTS, "审批人");
}
- validTask(task, executionId);
//校验审批人数量是否超过限制
validTaskAssignerCount(runtimeService, (TaskEntity) task, assigners);
}
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/listener/impl/InternalBpmnActivityEventListener_lo_Listener.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/listener/impl/InternalBpmnActivityEventListener_lo_Listener.java
index cde40df9d..77ce5a30d 100644
--- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/listener/impl/InternalBpmnActivityEventListener_lo_Listener.java
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/listener/impl/InternalBpmnActivityEventListener_lo_Listener.java
@@ -11,6 +11,7 @@ import cn.axzo.workflow.core.listener.AbstractBpmnEventListener;
import cn.axzo.workflow.core.listener.BpmnActivityEventListener;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.ListUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.common.engine.impl.cfg.TransactionState;
@@ -60,11 +61,16 @@ public class InternalBpmnActivityEventListener_lo_Listener extends AbstractBpmnE
if (!Boolean.TRUE.equals(refreshProperties.getAlterEnable())) {
return;
}
+ BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(execution.getProcessDefinitionId());
+ if (!refreshProperties.getAlterAllDefinitionKey()) {
+ if (!ListUtils.emptyIfNull(refreshProperties.getAlterDefinitionKeys()).contains(bpmnModel.getMainProcess().getId())) {
+ return;
+ }
+ }
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
TermNodePausingDTO dto = new TermNodePausingDTO(execution.getProcessInstanceId(), execution.getCurrentActivityId(), 0);
runtimeService.setVariable(execution.getProcessInstanceId(), BIZ_NODE_ALTER + execution.getCurrentActivityId(), dto);
- BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(execution.getProcessDefinitionId());
FlowElement flowElement = bpmnModel.getFlowElement(execution.getCurrentActivityId());
BpmnMetaParserHelper.getNodeType(flowElement).ifPresent(e -> {
if (Objects.equals(BpmnFlowNodeType.NODE_BUSINESS, e)) {
@@ -89,7 +95,9 @@ public class InternalBpmnActivityEventListener_lo_Listener extends AbstractBpmnE
TermNodeAddTimerJobDTO addTimerJobDTO = new TermNodeAddTimerJobDTO();
addTimerJobDTO.setProcessInstanceId(execution.getProcessInstanceId());
+ addTimerJobDTO.setProcessDefinitionId(execution.getProcessDefinitionId());
addTimerJobDTO.setActivityId(execution.getCurrentActivityId());
+ addTimerJobDTO.setActivityName(flowElement.getName());
addTimerJobDTO.setDelayTime(refreshProperties.getAlterInterval());
addTimerJobDTO.setTimeUnit(timeUnit);
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/repository/entity/ExtAxNodeAlterJob.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/repository/entity/ExtAxNodeAlterJob.java
new file mode 100644
index 000000000..ef6ec0c7f
--- /dev/null
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/repository/entity/ExtAxNodeAlterJob.java
@@ -0,0 +1,48 @@
+package cn.axzo.workflow.core.repository.entity;
+
+import cn.axzo.framework.data.mybatisplus.model.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.util.Date;
+
+/**
+ * 业务节点告警任务表
+ *
+ * @author wangli
+ * @since 2025-09-05 13:43
+ */
+@EqualsAndHashCode(callSuper = true)
+@TableName(value = "ext_ax_node_alter_job", autoResultMap = true)
+@Data
+@ToString(callSuper = true)
+public class ExtAxNodeAlterJob extends BaseEntity {
+ private static final long serialVersionUID = 461756492937079852L;
+
+ /**
+ * 流程实例 ID
+ */
+ private String processInstanceId;
+ /**
+ * 流程定义 ID
+ */
+ private String processDefinitionId;
+ /**
+ * 活动节点 ID
+ */
+ private String activityId;
+ /**
+ * 活动节点名称
+ */
+ private String activityName;
+ /**
+ * 告警事件
+ */
+ private Date alterTime;
+ /**
+ * 异常信息
+ */
+ private String exception;
+}
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/repository/mapper/ExtAxNodeAlterJobMapper.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/repository/mapper/ExtAxNodeAlterJobMapper.java
new file mode 100644
index 000000000..710206ab6
--- /dev/null
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/repository/mapper/ExtAxNodeAlterJobMapper.java
@@ -0,0 +1,22 @@
+package cn.axzo.workflow.core.repository.mapper;
+
+import cn.axzo.workflow.core.repository.entity.ExtAxNodeAlterJob;
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface ExtAxNodeAlterJobMapper extends BaseMapperX {
+
+ @Delete({
+ ""
+ })
+ int physicsDeleteBatchIds(@Param("ids") List ids);
+}
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/ExtAxNodeAlterJobService.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/ExtAxNodeAlterJobService.java
new file mode 100644
index 000000000..6ac3218f6
--- /dev/null
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/ExtAxNodeAlterJobService.java
@@ -0,0 +1,17 @@
+package cn.axzo.workflow.core.service;
+
+import cn.axzo.workflow.core.repository.entity.ExtAxNodeAlterJob;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * 业务节点告警表操作服务
+ *
+ * @author wangli
+ * @since 2024/4/3 10:40
+ */
+public interface ExtAxNodeAlterJobService extends IService {
+
+ boolean deleteByIds(List ids);
+}
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/ExtAxNodeAlterJobServiceImpl.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/ExtAxNodeAlterJobServiceImpl.java
new file mode 100644
index 000000000..041aea474
--- /dev/null
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/ExtAxNodeAlterJobServiceImpl.java
@@ -0,0 +1,31 @@
+package cn.axzo.workflow.core.service.impl;
+
+import cn.axzo.workflow.core.repository.entity.ExtAxNodeAlterJob;
+import cn.axzo.workflow.core.repository.mapper.ExtAxNodeAlterJobMapper;
+import cn.axzo.workflow.core.service.ExtAxNodeAlterJobService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 业务节点告警表操作服务实现类
+ *
+ * @author wangli
+ * @since 2025-09-05 13:50
+ */
+@Service
+@Slf4j
+public class ExtAxNodeAlterJobServiceImpl extends ServiceImpl implements ExtAxNodeAlterJobService {
+ @Resource
+ private ExtAxNodeAlterJobMapper extAxNodeAlterJobMapper;
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public boolean deleteByIds(List ids) {
+ return extAxNodeAlterJobMapper.physicsDeleteBatchIds(ids) > 0;
+ }
+}
diff --git a/workflow-engine-server/pom.xml b/workflow-engine-server/pom.xml
index 10cae3ff8..dc7817d5c 100644
--- a/workflow-engine-server/pom.xml
+++ b/workflow-engine-server/pom.xml
@@ -154,6 +154,10 @@
cn.axzo.nanopart
doc-api
+
+ cn.axzo.infra
+ adapter
+
diff --git a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/JobHttpHandler.java b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/JobHttpHandler.java
new file mode 100644
index 000000000..f9a66bf17
--- /dev/null
+++ b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/JobHttpHandler.java
@@ -0,0 +1,28 @@
+package cn.axzo.workflow.server.controller.web;
+
+import com.alibaba.fastjson.JSONObject;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.executor.XxlJobExecutor;
+import com.xxl.job.core.handler.IJobHandler;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author yanglin
+ */
+@RestController
+public class JobHttpHandler {
+
+ @PostMapping("/jobs/{jobName}")
+ ReturnT exec(@PathVariable String jobName,
+ @RequestBody(required = false) JSONObject paramObj) throws Exception {
+ IJobHandler jobHandler = XxlJobExecutor.loadJobHandler(jobName);
+ if (jobHandler == null)
+ return new ReturnT<>(ReturnT.FAIL_CODE, String.format("找不到job: %s", jobName));
+ jobHandler.execute();
+ return ReturnT.SUCCESS;
+ }
+
+}
\ No newline at end of file
diff --git a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/xxljob/NodeAlterJobHandler.java b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/xxljob/NodeAlterJobHandler.java
new file mode 100644
index 000000000..6b0944db4
--- /dev/null
+++ b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/xxljob/NodeAlterJobHandler.java
@@ -0,0 +1,132 @@
+package cn.axzo.workflow.server.xxljob;
+
+import cn.axzo.basics.common.util.NumberUtil;
+import cn.axzo.framework.jackson.utility.JSON;
+import cn.axzo.infra.xxl220to250.IJobHandler;
+import cn.axzo.workflow.common.model.dto.AlterDTO;
+import cn.axzo.workflow.common.model.response.category.CategoryItemVO;
+import cn.axzo.workflow.core.common.utils.SpringContextUtils;
+import cn.axzo.workflow.core.conf.SupportRefreshProperties;
+import cn.axzo.workflow.core.listener.Alter;
+import cn.axzo.workflow.core.repository.entity.ExtAxNodeAlterJob;
+import cn.axzo.workflow.core.service.CategoryService;
+import cn.axzo.workflow.core.service.ExtAxNodeAlterJobService;
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.context.XxlJobHelper;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.ListUtils;
+import org.flowable.engine.RuntimeService;
+import org.flowable.engine.TaskService;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.spring.SpringProcessEngineConfiguration;
+import org.flowable.task.api.Task;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import static cn.axzo.workflow.common.constant.BpmnConstants.BPM_MODEL_CATEGORY;
+
+/**
+ * 调度业务节点告警定时任务
+ *
+ * @author wangli
+ * @since 2025-09-05 11:19
+ */
+@Component
+@RequiredArgsConstructor
+@Slf4j
+public class NodeAlterJobHandler extends IJobHandler {
+
+ private final ExtAxNodeAlterJobService extAxNodeAlterJobService;
+ private final CategoryService categoryService;
+ private final SpringProcessEngineConfiguration processEngineConfiguration;
+ private final SupportRefreshProperties refreshProperties;
+
+ @XxlJob("nodeAlterJobHandler")
+ @Override
+ public ReturnT execute(String param) throws Exception {
+ List jobs = extAxNodeAlterJobService.list(new LambdaQueryWrapper()
+ .le(ExtAxNodeAlterJob::getAlterTime, new Date()));
+ if (CollectionUtils.isEmpty(jobs)) {
+ XxlJobHelper.log("没有需要处理的业务节点告警任务");
+ return ReturnT.SUCCESS;
+ }
+
+ List executedJobs = new ArrayList<>();
+ RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
+ TaskService taskService = processEngineConfiguration.getTaskService();
+ jobs.forEach(e -> {
+ XxlJobHelper.log("start execution of job: {}", JSON.toJSONString(e));
+ ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(e.getProcessInstanceId()).singleResult();
+ if (!refreshProperties.getAlterAllDefinitionKey()) {
+ if (!ListUtils.emptyIfNull(refreshProperties.getAlterDefinitionKeys()).contains(processInstance.getProcessDefinitionKey())) {
+ XxlJobHelper.log("skip alter by config");
+ return;
+ }
+ }
+ if (Objects.isNull(processInstance)) {
+ executedJobs.add(e);
+ return;
+ }
+ List tasks = taskService.createTaskQuery()
+ .processInstanceId(e.getProcessInstanceId())
+ .taskDefinitionKey(e.getActivityId())
+ .active().list();
+
+ StringBuilder sb = new StringBuilder();
+ tasks.forEach(t -> {
+ sb.append("id:").append(e.getId()).append(", assignee: ").append(t.getAssignee());
+ });
+ XxlJobHelper.log("tasks size:{}, info: {}", tasks.size(), com.alibaba.fastjson.JSON.toJSONString(sb));
+ if (CollectionUtils.isEmpty(tasks) || tasks.size() > 1 || hasAssignee(tasks.get(0).getAssignee())) {
+ executedJobs.add(e);
+ return;
+ }
+
+ Optional category = categoryService.get(BPM_MODEL_CATEGORY, processInstance.getProcessDefinitionKey());
+
+ sendAlter(processInstance, category, e, tasks.get(0));
+
+ executedJobs.add(e);
+ XxlJobHelper.log("end execution of job: {}", JSON.toJSONString(e));
+ });
+
+ extAxNodeAlterJobService.deleteByIds(executedJobs.stream().map(ExtAxNodeAlterJob::getId).collect(Collectors.toList()));
+ return ReturnT.SUCCESS;
+ }
+
+ private void sendAlter(ProcessInstance processInstance, Optional category, ExtAxNodeAlterJob job, Task task) {
+ // 发送告警对象
+ Alter alter = SpringContextUtils.getBean(Alter.class);
+ AlterDTO alterDTO = new AlterDTO();
+ alterDTO.setProcessDefinitionKey(processInstance.getProcessDefinitionKey());
+ alterDTO.setProcessDefinitionName(category.orElse(new CategoryItemVO()).getLabel());
+ alterDTO.setProcessInstanceId(job.getProcessInstanceId());
+ alterDTO.setActivityId(job.getActivityId());
+ alterDTO.setTaskId(task.getId());
+ alterDTO.setStartTime(task.getCreateTime());
+ alterDTO.setPrettyStartTime(DateUtil.formatDateTime(task.getCreateTime()));
+ if (Boolean.TRUE.equals(refreshProperties.getAlterSendDingTalk())) {
+ alter.invoke(alterDTO);
+ }
+ }
+
+ private Boolean hasAssignee(String assignee) {
+ if (!StringUtils.hasText(assignee)) {
+ return false;
+ }
+ String[] split = assignee.split("\\|");
+ return split.length == 2 && NumberUtil.isPositiveNumber(Long.valueOf(split[1]));
+ }
+}