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])); + } +}