diff --git a/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/api/AtuPlanInfoRestfulCtrl.java b/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/api/AtuPlanInfoRestfulCtrl.java index e856ab7..5b755e6 100644 --- a/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/api/AtuPlanInfoRestfulCtrl.java +++ b/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/api/AtuPlanInfoRestfulCtrl.java @@ -5,20 +5,26 @@ package net.northking.cctp.executePlan.api; import cn.gjing.tools.auth.annotation.RequiredPermissions; +import cn.hutool.core.collection.CollUtil; import cn.hutool.json.JSONUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import net.northking.cctp.common.exception.PlatformRuntimeException; import net.northking.cctp.common.http.ResultWrapper; import net.northking.cctp.common.security.authentication.NKSecurityContext; import net.northking.cctp.executePlan.api.service.AtuPlanBatchApiService; import net.northking.cctp.executePlan.api.service.AtuPlanInfoApiService; import net.northking.cctp.executePlan.api.service.AtuPlanTaskApiService; import net.northking.cctp.executePlan.constants.PlanConstant; +import net.northking.cctp.executePlan.constants.RedisConstant; +import net.northking.cctp.executePlan.db.entity.AtuPlanBatch; +import net.northking.cctp.executePlan.db.entity.AtuPlanTask; import net.northking.cctp.executePlan.dto.planBatch.BatchRetryDto; import net.northking.cctp.executePlan.dto.planInfo.AtuPlanInfoDetailDto; import net.northking.cctp.executePlan.dto.planInfo.AtuPlanRunDto; import net.northking.cctp.executePlan.dto.planTask.AtuPlanTaskDetailDto; import net.northking.cctp.executePlan.dto.planTask.AtuTaskSendBugDto; +import net.northking.cctp.executePlan.exception.ExecPlanError; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -27,7 +33,9 @@ import org.springframework.integration.redis.util.RedisLockRegistry; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; import java.util.Map; +import java.util.concurrent.locks.Lock; /** * 执行计划表 => Restful 类型 HTTP/HTTPS 接口 @@ -205,7 +213,28 @@ public class AtuPlanInfoRestfulCtrl { logger.info("start taskRetry: retryDto =======> " + JSONUtil.toJsonStr(retryDto)); ResultWrapper wrapper = new ResultWrapper<>(); - Boolean result = taskApiService.taskRetry(retryDto); + Boolean result = false; + if (retryDto.getTaskIdList() != null && !retryDto.getTaskIdList().isEmpty()) { + logger.debug("查询需要重试的任务信息"); + List planTaskList = taskApiService.findByPrimaryKeys(retryDto.getTaskIdList()); + logger.debug("查询需要重试的任务信息数量:{}", planTaskList.size()); + if (CollUtil.isEmpty(planTaskList)) { + throw new PlatformRuntimeException(ExecPlanError.TASK_INFO_IS_NULL); + } + AtuPlanTask firstFailTask = planTaskList.get(0); + AtuPlanBatch planBatch = batchApiService.findByPrimaryKey(firstFailTask.getBatchId()); + // 加个锁,当选择的任务量比较多的时候,需要时间进行处理 + Lock lock = redisLockRegistry.obtain(String.format("%s%s", RedisConstant.PLAN_BATCH_RETRY_LOCK_PRE, planBatch.getId())); + if (!lock.tryLock()) { + // 获取不到锁,正在处理重试 + throw new PlatformRuntimeException(ExecPlanError.BATCH_IS_DEALING_WITH_RETRY); + } + try { + result = taskApiService.taskRetry(retryDto); + } finally { + lock.unlock(); + } + } logger.info("end taskRetry"); diff --git a/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/api/service/AtuPlanTaskApiService.java b/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/api/service/AtuPlanTaskApiService.java index d08d5b4..cafda96 100644 --- a/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/api/service/AtuPlanTaskApiService.java +++ b/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/api/service/AtuPlanTaskApiService.java @@ -128,6 +128,14 @@ public interface AtuPlanTaskApiService extends ExcelService */ AtuPlanTask findByPrimaryKey(String id); + /** + * 根据多个主键查询任务信息 + * + * @param keys 主键集合 + * @return + */ + List findByPrimaryKeys(List keys); + /** * 任务重试 * @param retryDto 任务id diff --git a/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/api/service/AtuPlanTaskApiServiceImpl.java b/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/api/service/AtuPlanTaskApiServiceImpl.java index de345dd..c48ded6 100644 --- a/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/api/service/AtuPlanTaskApiServiceImpl.java +++ b/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/api/service/AtuPlanTaskApiServiceImpl.java @@ -1470,6 +1470,11 @@ public class AtuPlanTaskApiServiceImpl extends AbstractExcelService return this.atuPlanTaskService.findByPrimaryKey(id); } + @Override + public List findByPrimaryKeys(List keys) { + return this.atuPlanTaskService.findByPrimaryKeys(keys); + } + @Override @Transactional(rollbackFor = Exception.class) public Boolean taskRetry(BatchRetryDto retryDto) { @@ -1486,274 +1491,264 @@ public class AtuPlanTaskApiServiceImpl extends AbstractExcelService PlanConstant.BATCH_EXECUTING_STATUS.equals(planBatch.getStatus())) { throw new PlatformRuntimeException(ExecPlanError.BATCH_NOT_FINISH); } - // 加个锁,当选择的任务量比较多的时候,需要时间进行处理 - Lock lock = redisLockRegistry.obtain(String.format("%s%s", RedisConstant.PLAN_BATCH_RETRY_LOCK_PRE, planBatch.getId())); - if (!lock.tryLock()) { - // 获取不到锁,正在处理重试 - throw new PlatformRuntimeException(ExecPlanError.BATCH_IS_DEALING_WITH_RETRY); + logger.debug("根据批次编号[{}]查询计划信息", firstFailTask.getBatchId()); + AtuPlanInfo planInfo = atuPlanInfoApiService.findByBatchId(firstFailTask.getBatchId()); + if (planInfo == null) { + throw new PlatformRuntimeException(ExecPlanError.PLAN_IS_NULL); } - try { - logger.debug("根据批次编号[{}]查询计划信息", firstFailTask.getBatchId()); - AtuPlanInfo planInfo = atuPlanInfoApiService.findByBatchId(firstFailTask.getBatchId()); - if (planInfo == null) { - throw new PlatformRuntimeException(ExecPlanError.PLAN_IS_NULL); - } - logger.debug("更新计划和批次状态"); - String planStatus = ""; - if (planBatch.getTaskTotal() > retryDto.getTaskIdList().size()) { - logger.debug("部分任务重试,批次状态为:{},计划状态为:{}", PlanConstant.BATCH_EXECUTING_STATUS, - PlanConstant.PLAN_EXECUTING_STATUS); - planBatch.setStatus(PlanConstant.BATCH_EXECUTING_STATUS); - planStatus = PlanConstant.PLAN_EXECUTING_STATUS; - } else { - logger.debug("全部任务重试,批次状态为:{},计划状态为:{}", PlanConstant.BATCH_WAITING_STATUS, - PlanConstant.PLAN_WAITING_STATUS); - planBatch.setStatus(PlanConstant.BATCH_WAITING_STATUS); - planStatus = PlanConstant.PLAN_WAITING_STATUS; + logger.debug("更新计划和批次状态"); + String planStatus = ""; + if (planBatch.getTaskTotal() > retryDto.getTaskIdList().size()) { + logger.debug("部分任务重试,批次状态为:{},计划状态为:{}", PlanConstant.BATCH_EXECUTING_STATUS, + PlanConstant.PLAN_EXECUTING_STATUS); + planBatch.setStatus(PlanConstant.BATCH_EXECUTING_STATUS); + planStatus = PlanConstant.PLAN_EXECUTING_STATUS; + } else { + logger.debug("全部任务重试,批次状态为:{},计划状态为:{}", PlanConstant.BATCH_WAITING_STATUS, + PlanConstant.PLAN_WAITING_STATUS); + planBatch.setStatus(PlanConstant.BATCH_WAITING_STATUS); + planStatus = PlanConstant.PLAN_WAITING_STATUS; + } + List deletedFilePath = new ArrayList<>(); + List taskIds = new ArrayList<>(); + planTaskList.forEach(task -> { + logger.info("普通脚本任务id:{},执行结果文件:{}", task.getId(), task.getExecResultFile()); + taskIds.add(task.getId()); + String execResultFile = task.getExecResultFile(); + if (StringUtils.isNotBlank(execResultFile)) { + deletedFilePath.add(execResultFile); + getActualImagePath(deletedFilePath, execResultFile); } - List deletedFilePath = new ArrayList<>(); - List taskIds = new ArrayList<>(); - planTaskList.forEach(task -> { - logger.info("普通脚本任务id:{},执行结果文件:{}", task.getId(), task.getExecResultFile()); - taskIds.add(task.getId()); - String execResultFile = task.getExecResultFile(); + String perDataPath = task.getPerDataPath(); + if (StringUtils.isNotBlank(perDataPath)) { + deletedFilePath.add("/" + MinioPathUtils.idToPath(perDataPath)[1]); + } + String videoUrl = task.getVideoUrl(); + if (StringUtils.isNotBlank(videoUrl)) { + deletedFilePath.add("/" + MinioPathUtils.idToPath(videoUrl)[1]); + } + // 场景用例脚本json是单独的需要删除 + if (task.getCaseType().equals("5")) { + deletedFilePath.add("/" + MinioPathUtils.idToPath(task.getScriptJson())[1]); + } + }); + if (!CollectionUtils.isEmpty(taskIds)) { + List atuPlanSceneCaseTaskList = atuPlanSceneCaseTaskService.querySceneCaseTasksByTaskIds(taskIds); + atuPlanSceneCaseTaskList.forEach(atuPlanSceneCaseTask -> { + logger.info("场景任务id:{},节点任务id:{},执行结果文件:{}", atuPlanSceneCaseTask.getTaskId(), atuPlanSceneCaseTask.getId(), atuPlanSceneCaseTask.getExecResultFile()); + String videoUrl = atuPlanSceneCaseTask.getVideoUrl(); + if (StringUtils.isNotBlank(videoUrl)) { + deletedFilePath.add("/" + MinioPathUtils.idToPath(videoUrl)[1]); + } + String perDataPath = atuPlanSceneCaseTask.getPerDataPath(); + if (StringUtils.isNotBlank(perDataPath)) { + deletedFilePath.add("/" + MinioPathUtils.idToPath(perDataPath)[1]); + } + String execResultFile = atuPlanSceneCaseTask.getExecResultFile(); if (StringUtils.isNotBlank(execResultFile)) { deletedFilePath.add(execResultFile); getActualImagePath(deletedFilePath, execResultFile); } - String perDataPath = task.getPerDataPath(); - if (StringUtils.isNotBlank(perDataPath)) { - deletedFilePath.add("/" + MinioPathUtils.idToPath(perDataPath)[1]); - } - String videoUrl = task.getVideoUrl(); - if (StringUtils.isNotBlank(videoUrl)) { - deletedFilePath.add("/" + MinioPathUtils.idToPath(videoUrl)[1]); - } - // 场景用例脚本json是单独的需要删除 - if (task.getCaseType().equals("5")) { - deletedFilePath.add("/" + MinioPathUtils.idToPath(task.getScriptJson())[1]); - } }); - if (!CollectionUtils.isEmpty(taskIds)) { - List atuPlanSceneCaseTaskList = atuPlanSceneCaseTaskService.querySceneCaseTasksByTaskIds(taskIds); - atuPlanSceneCaseTaskList.forEach(atuPlanSceneCaseTask -> { - logger.info("场景任务id:{},节点任务id:{},执行结果文件:{}", atuPlanSceneCaseTask.getTaskId(), atuPlanSceneCaseTask.getId(), atuPlanSceneCaseTask.getExecResultFile()); - String videoUrl = atuPlanSceneCaseTask.getVideoUrl(); - if (StringUtils.isNotBlank(videoUrl)) { - deletedFilePath.add("/" + MinioPathUtils.idToPath(videoUrl)[1]); - } - String perDataPath = atuPlanSceneCaseTask.getPerDataPath(); - if (StringUtils.isNotBlank(perDataPath)) { - deletedFilePath.add("/" + MinioPathUtils.idToPath(perDataPath)[1]); - } - String execResultFile = atuPlanSceneCaseTask.getExecResultFile(); - if (StringUtils.isNotBlank(execResultFile)) { - deletedFilePath.add(execResultFile); - getActualImagePath(deletedFilePath, execResultFile); - } - }); - } - if (!CollectionUtils.isEmpty(deletedFilePath)) { - AssociatedFilesDto associatedFilesDto = new AssociatedFilesDto(); - associatedFilesDto.setObjId("-1"); - associatedFilesDto.setFileIds(deletedFilePath); - attachmentFeignClient.associatedFiles(associatedFilesDto); - } - planBatchApiService.updateByEntity(planBatch); - atuPlanInfoApiService.updateStatusByLastBatchId(planBatch.getId(), planStatus); - - logger.info("查询计划数据集中未被选择的意图数据"); - Set scriptIdSet = new HashSet<>(); - Map> envScriptMap = new HashMap<>(); - Map> envScriptTaskMap = new HashMap<>(); - List taskIdList = new ArrayList<>(); - for (AtuPlanTask planTask : planTaskList) { - taskIdList.add(planTask.getId()); - scriptIdSet.add(planTask.getScriptId()); - List scriptIdList = new ArrayList<>(); - if (envScriptMap.containsKey(planTask.getEnvId())) { - scriptIdList = envScriptMap.get(planTask.getEnvId()); - } - scriptIdList.add(planTask.getScriptId()); - envScriptMap.put(planTask.getEnvId(), scriptIdList); - String key = planTask.getEnvId() + "-" + planTask.getScriptId(); - List envScriptTaskList = new ArrayList<>(); - if (envScriptTaskMap.containsKey(key)) { - envScriptTaskList = envScriptTaskMap.get(key); - } - envScriptTaskList.add(planTask); - envScriptTaskMap.put(key, envScriptTaskList); - } - logger.debug("获取最新的输入项数据"); - Map taskParamsMap = getRetryTaskInputInfo(envScriptTaskMap, envScriptMap); - logger.debug("最新输入项数据大小:{}", taskParamsMap.size()); - - logger.debug("start 初始化批次缓存数据"); - taskRetryInitCache(taskIdList, planBatch); - logger.debug("end 初始化批次缓存数据"); - - logger.debug("查询脚本最新数据"); - logger.debug("脚本数量:{}", scriptIdSet.size()); - Map scriptMap = queryScriptDetailMap(scriptIdSet); - logger.debug("脚本最新信息数量:{}", scriptMap.size()); - - Map caseTypeMap = new HashMap<>(); - caseTypeMap.put("hasPc", false); - caseTypeMap.put("hasMob", false); - caseTypeMap.put("hasInterface", false); - for (AtuPlanTask planTask : planTaskList) { - String status = planTask.getStatus(); - logger.debug("原任务状态为: {}", status); - // 判断任务是否开始执行 - if (PlanConstant.TASK_WAIT_EXECUTE_STATUS.equals(planTask.getStatus()) || - PlanConstant.TASK_START_EXECUTE_STATUS.equals(planTask.getStatus())) { - throw new PlatformRuntimeException(ExecPlanError.TASK_NOT_FINISH); - } - logger.debug("修改任务脚本为最新脚本信息"); - if (scriptMap.containsKey(planTask.getScriptId())) { - AtuScriptDetailDto atuScriptDetailDto = scriptMap.get(planTask.getScriptId()); - planTask.setVersionId(atuScriptDetailDto.getVersionId()); - planTask.setVersionName(atuScriptDetailDto.getVersionName()); - planTask.setScriptName(atuScriptDetailDto.getScriptName()); - planTask.setScriptJson(atuScriptDetailDto.getScriptPath()); - planTask.setAppId(queryAppId(planInfo.getId(), atuScriptDetailDto.getPlatformType(), - atuScriptDetailDto.getAppPackage(), atuScriptDetailDto.getScriptType())); - } - - logger.debug("生成任务执行信息"); - AtuTaskExecDto taskExecDto = new AtuTaskExecDto(); - BeanUtil.copyProperties(planInfo, taskExecDto); - taskExecDto.setPlanId(planInfo.getId()); - taskExecDto.setFailRetryNum(planInfo.getFailRetryCount()); - taskExecDto.setBatchId(planTask.getBatchId()); - taskExecDto.setTaskId(planTask.getId()); - taskExecDto.setCaseId(planTask.getCaseId()); - taskExecDto.setEnvId(planTask.getEnvId()); - String type = planTask.getCaseType(); - taskExecDto.setCaseType(type); - String scriptPath = planTask.getScriptJson(); - - Map caseParams = new HashMap<>(); - if (taskParamsMap.containsKey(planTask.getId())) { - logger.debug("重试使用新数据"); - caseParams = JSONUtil.toBean(taskParamsMap.get(planTask.getId()), Map.class); - } else { - if (StrUtil.isNotBlank(planTask.getCaseParam())) { - logger.debug("使用旧数据重试"); - caseParams = JSONUtil.toBean(planTask.getCaseParam(), Map.class); - } - } - // 更新静态数据与模糊数据为最新值 - caseParams = this.handleQuoteData(caseParams, planTask.getEnvId(), planInfo.getProjectId()); - planTask.setCaseParam(JSONUtil.toJsonStr(caseParams)); - - String appId = planTask.getAppId(); - AtuSceneNodeExecDto sceneNodeExecDto = null; - - //判断是否场景任务 - if (PlanConstant.SCRIPT_TYPE_SCENE.equals(planTask.getCaseType())) { - // 调用脚本服务获取场景首节点信息,通知脚本服务场景重新发起 - logger.debug("查询场景脚本的首节点信息"); - SceneFirstNodeDto firstNodeDto = new SceneFirstNodeDto(); - firstNodeDto.setTaskId(planTask.getId()); - firstNodeDto.setCaseId(planTask.getCaseId()); - String scriptId = planTask.getScriptId(); - firstNodeDto.setScriptId(scriptId); - firstNodeDto.setParamMap(caseParams); - logger.debug("查询参数 => {}", JSONUtil.toJsonStr(firstNodeDto)); - AtuSceneNodeInfoDto nodeInfo; - try { - ResultWrapper firstNodeResult = publicFeignClient.getFirstNode(firstNodeDto); - if (firstNodeResult.isSuccess() && firstNodeResult.getData() != null) { - logger.debug("首节点信息为 => " + JSONUtil.toJsonStr(firstNodeResult)); - sceneNodeExecDto = firstNodeResult.getData(); - nodeInfo = sceneNodeExecDto.getNodeInfo(); - } else { - throw new RuntimeException("获取场景脚本[ " + scriptId + "]首节点信息异常," + firstNodeResult.getMessage()); - } - } catch (Exception e) { - logger.error("获取场景首节点信息异常", e); - throw new PlatformRuntimeException(ExecPlanError.GET_SCENE_FIRST_NODE_FAIL); - } - if (ObjectUtil.isNull(nodeInfo)) { - throw new PlatformRuntimeException(ExecPlanError.SCENE_FIRST_NODE_INFO_IS_NULL); - } - - String sceneTaskId = IdUtil.simpleUUID(); - taskExecDto.setTaskId(sceneTaskId); - scriptPath = nodeInfo.getScriptPath(); - caseParams = nodeInfo.getCaseParam(); - appId = queryAppId(taskExecDto.getPlanId(), nodeInfo.getPlatformType(), - nodeInfo.getAppPackage(), nodeInfo.getNodeType()); - type = nodeInfo.getNodeType(); - - logger.debug("清理原节点任务"); - AtuPlanSceneCaseTask deleteParams = new AtuPlanSceneCaseTask(); - deleteParams.setTaskId(planTask.getId()); - int rows = atuPlanSceneCaseTaskService.deleteByExample(deleteParams); - if (rows <= 0) { - logger.error("清理原场景节点任务失败"); - throw new PlatformRuntimeException(ExecPlanError.CLEAR_SCENE_NODE_TASK_FAIL); - } - logger.debug("插入新节点任务"); - AtuPlanSceneCaseTask planSceneCaseTask = new AtuPlanSceneCaseTask(); - planSceneCaseTask.setId(sceneTaskId); - planSceneCaseTask.setTaskId(planTask.getId()); - planSceneCaseTask.setScriptId(nodeInfo.getScriptId()); - planSceneCaseTask.setVersionId(nodeInfo.getVersionId()); - planSceneCaseTask.setVersionName(nodeInfo.getVersionName()); - planSceneCaseTask.setScriptName(nodeInfo.getScriptName()); - planSceneCaseTask.setScriptJson(nodeInfo.getScriptPath()); - planSceneCaseTask.setNodeId(nodeInfo.getNodeId()); - planSceneCaseTask.setNodeType(nodeInfo.getNodeType()); - if (CollUtil.isNotEmpty(nodeInfo.getCaseParam())) { - planSceneCaseTask.setNodeParams(JSONUtil.toJsonStr(nodeInfo.getCaseParam())); - } - planSceneCaseTask.setCreatedTime(new Date()); - planSceneCaseTask.setStatus(PlanConstant.TASK_WAIT_EXECUTE_STATUS); - planSceneCaseTask.setScriptJson(nodeInfo.getScriptPath()); - atuPlanSceneCaseTaskService.insert(planSceneCaseTask); - - } - taskExecDto.setScriptPath(scriptPath); - taskExecDto.setCaseParams(caseParams); - taskExecDto.setAppId(appId); - - logger.debug("修改原任务状态"); - planTask.setEngineId(""); - planTask.setDeviceId(""); - planTask.setAppId(""); - planTask.setStatus(PlanConstant.TASK_WAIT_EXECUTE_STATUS); - planTask.setStartTime(null); - planTask.setEndTime(null); - planTask.setErrorMsg(""); - planTask.setVideoUrl(""); - planTask.setExecResultFile(""); - planTask.setBugId(""); - if (sceneNodeExecDto != null && sceneNodeExecDto.getSceneScriptUrl() != null) { - planTask.setScriptJson(sceneNodeExecDto.getSceneScriptUrl()); - } else { - logger.info("首节点返回sceneScriptUrl为空" + sceneNodeExecDto); - } - int rows = atuPlanTaskService.updateByPrimaryKey(planTask); - if (rows <= 0) { - throw new PlatformRuntimeException(ExecPlanError.INIT_TASK_INFO_FAIL); - } - - logger.debug("发送任务执行信息至消息队列"); - sendToQueue(taskExecDto.getBatchId(), taskExecDto, type); - - atuPlanInfoApiService.handleAutoType(PlanConstant.SCRIPT_TYPE_SCENE, caseTypeMap); - } - - logger.debug("计划批次重新发起委托"); - atuPlanInfoApiService.handlePlanDevice(planInfo.getId(), planInfo.getPriority(), planBatch.getId(), - retryDto.getHasOfflineDevice(), caseTypeMap, true); - return true; - } finally { - lock.unlock(); } + if (!CollectionUtils.isEmpty(deletedFilePath)) { + AssociatedFilesDto associatedFilesDto = new AssociatedFilesDto(); + associatedFilesDto.setObjId("-1"); + associatedFilesDto.setFileIds(deletedFilePath); + attachmentFeignClient.associatedFiles(associatedFilesDto); + } + planBatchApiService.updateByEntity(planBatch); + atuPlanInfoApiService.updateStatusByLastBatchId(planBatch.getId(), planStatus); + + logger.info("查询计划数据集中未被选择的意图数据"); + Set scriptIdSet = new HashSet<>(); + Map> envScriptMap = new HashMap<>(); + Map> envScriptTaskMap = new HashMap<>(); + List taskIdList = new ArrayList<>(); + for (AtuPlanTask planTask : planTaskList) { + taskIdList.add(planTask.getId()); + scriptIdSet.add(planTask.getScriptId()); + List scriptIdList = new ArrayList<>(); + if (envScriptMap.containsKey(planTask.getEnvId())) { + scriptIdList = envScriptMap.get(planTask.getEnvId()); + } + scriptIdList.add(planTask.getScriptId()); + envScriptMap.put(planTask.getEnvId(), scriptIdList); + String key = planTask.getEnvId() + "-" + planTask.getScriptId(); + List envScriptTaskList = new ArrayList<>(); + if (envScriptTaskMap.containsKey(key)) { + envScriptTaskList = envScriptTaskMap.get(key); + } + envScriptTaskList.add(planTask); + envScriptTaskMap.put(key, envScriptTaskList); + } + logger.debug("获取最新的输入项数据"); + Map taskParamsMap = getRetryTaskInputInfo(envScriptTaskMap, envScriptMap); + logger.debug("最新输入项数据大小:{}", taskParamsMap.size()); + + logger.debug("start 初始化批次缓存数据"); + taskRetryInitCache(taskIdList, planBatch); + logger.debug("end 初始化批次缓存数据"); + + logger.debug("查询脚本最新数据"); + logger.debug("脚本数量:{}", scriptIdSet.size()); + Map scriptMap = queryScriptDetailMap(scriptIdSet); + logger.debug("脚本最新信息数量:{}", scriptMap.size()); + + Map caseTypeMap = new HashMap<>(); + caseTypeMap.put("hasPc", false); + caseTypeMap.put("hasMob", false); + caseTypeMap.put("hasInterface", false); + for (AtuPlanTask planTask : planTaskList) { + String status = planTask.getStatus(); + logger.debug("原任务状态为: {}", status); + // 判断任务是否开始执行 + if (PlanConstant.TASK_WAIT_EXECUTE_STATUS.equals(planTask.getStatus()) || + PlanConstant.TASK_START_EXECUTE_STATUS.equals(planTask.getStatus())) { + throw new PlatformRuntimeException(ExecPlanError.TASK_NOT_FINISH); + } + logger.debug("修改任务脚本为最新脚本信息"); + if (scriptMap.containsKey(planTask.getScriptId())) { + AtuScriptDetailDto atuScriptDetailDto = scriptMap.get(planTask.getScriptId()); + planTask.setVersionId(atuScriptDetailDto.getVersionId()); + planTask.setVersionName(atuScriptDetailDto.getVersionName()); + planTask.setScriptName(atuScriptDetailDto.getScriptName()); + planTask.setScriptJson(atuScriptDetailDto.getScriptPath()); + planTask.setAppId(queryAppId(planInfo.getId(), atuScriptDetailDto.getPlatformType(), + atuScriptDetailDto.getAppPackage(), atuScriptDetailDto.getScriptType())); + } + + logger.debug("生成任务执行信息"); + AtuTaskExecDto taskExecDto = new AtuTaskExecDto(); + BeanUtil.copyProperties(planInfo, taskExecDto); + taskExecDto.setPlanId(planInfo.getId()); + taskExecDto.setFailRetryNum(planInfo.getFailRetryCount()); + taskExecDto.setBatchId(planTask.getBatchId()); + taskExecDto.setTaskId(planTask.getId()); + taskExecDto.setCaseId(planTask.getCaseId()); + taskExecDto.setEnvId(planTask.getEnvId()); + String type = planTask.getCaseType(); + taskExecDto.setCaseType(type); + String scriptPath = planTask.getScriptJson(); + + Map caseParams = new HashMap<>(); + if (taskParamsMap.containsKey(planTask.getId())) { + logger.debug("重试使用新数据"); + caseParams = JSONUtil.toBean(taskParamsMap.get(planTask.getId()), Map.class); + } else { + if (StrUtil.isNotBlank(planTask.getCaseParam())) { + logger.debug("使用旧数据重试"); + caseParams = JSONUtil.toBean(planTask.getCaseParam(), Map.class); + } + } + // 更新静态数据与模糊数据为最新值 + caseParams = this.handleQuoteData(caseParams, planTask.getEnvId(), planInfo.getProjectId()); + planTask.setCaseParam(JSONUtil.toJsonStr(caseParams)); + + String appId = planTask.getAppId(); + AtuSceneNodeExecDto sceneNodeExecDto = null; + + //判断是否场景任务 + if (PlanConstant.SCRIPT_TYPE_SCENE.equals(planTask.getCaseType())) { + // 调用脚本服务获取场景首节点信息,通知脚本服务场景重新发起 + logger.debug("查询场景脚本的首节点信息"); + SceneFirstNodeDto firstNodeDto = new SceneFirstNodeDto(); + firstNodeDto.setTaskId(planTask.getId()); + firstNodeDto.setCaseId(planTask.getCaseId()); + String scriptId = planTask.getScriptId(); + firstNodeDto.setScriptId(scriptId); + firstNodeDto.setParamMap(caseParams); + logger.debug("查询参数 => {}", JSONUtil.toJsonStr(firstNodeDto)); + AtuSceneNodeInfoDto nodeInfo; + try { + ResultWrapper firstNodeResult = publicFeignClient.getFirstNode(firstNodeDto); + if (firstNodeResult.isSuccess() && firstNodeResult.getData() != null) { + logger.debug("首节点信息为 => " + JSONUtil.toJsonStr(firstNodeResult)); + sceneNodeExecDto = firstNodeResult.getData(); + nodeInfo = sceneNodeExecDto.getNodeInfo(); + } else { + throw new RuntimeException("获取场景脚本[ " + scriptId + "]首节点信息异常," + firstNodeResult.getMessage()); + } + } catch (Exception e) { + logger.error("获取场景首节点信息异常", e); + throw new PlatformRuntimeException(ExecPlanError.GET_SCENE_FIRST_NODE_FAIL); + } + if (ObjectUtil.isNull(nodeInfo)) { + throw new PlatformRuntimeException(ExecPlanError.SCENE_FIRST_NODE_INFO_IS_NULL); + } + + String sceneTaskId = IdUtil.simpleUUID(); + taskExecDto.setTaskId(sceneTaskId); + scriptPath = nodeInfo.getScriptPath(); + caseParams = nodeInfo.getCaseParam(); + appId = queryAppId(taskExecDto.getPlanId(), nodeInfo.getPlatformType(), + nodeInfo.getAppPackage(), nodeInfo.getNodeType()); + type = nodeInfo.getNodeType(); + + logger.debug("清理原节点任务"); + AtuPlanSceneCaseTask deleteParams = new AtuPlanSceneCaseTask(); + deleteParams.setTaskId(planTask.getId()); + int rows = atuPlanSceneCaseTaskService.deleteByExample(deleteParams); + if (rows <= 0) { + logger.error("清理原场景节点任务失败"); + throw new PlatformRuntimeException(ExecPlanError.CLEAR_SCENE_NODE_TASK_FAIL); + } + logger.debug("插入新节点任务"); + AtuPlanSceneCaseTask planSceneCaseTask = new AtuPlanSceneCaseTask(); + planSceneCaseTask.setId(sceneTaskId); + planSceneCaseTask.setTaskId(planTask.getId()); + planSceneCaseTask.setScriptId(nodeInfo.getScriptId()); + planSceneCaseTask.setVersionId(nodeInfo.getVersionId()); + planSceneCaseTask.setVersionName(nodeInfo.getVersionName()); + planSceneCaseTask.setScriptName(nodeInfo.getScriptName()); + planSceneCaseTask.setScriptJson(nodeInfo.getScriptPath()); + planSceneCaseTask.setNodeId(nodeInfo.getNodeId()); + planSceneCaseTask.setNodeType(nodeInfo.getNodeType()); + if (CollUtil.isNotEmpty(nodeInfo.getCaseParam())) { + planSceneCaseTask.setNodeParams(JSONUtil.toJsonStr(nodeInfo.getCaseParam())); + } + planSceneCaseTask.setCreatedTime(new Date()); + planSceneCaseTask.setStatus(PlanConstant.TASK_WAIT_EXECUTE_STATUS); + planSceneCaseTask.setScriptJson(nodeInfo.getScriptPath()); + atuPlanSceneCaseTaskService.insert(planSceneCaseTask); + + } + taskExecDto.setScriptPath(scriptPath); + taskExecDto.setCaseParams(caseParams); + taskExecDto.setAppId(appId); + + logger.debug("修改原任务状态"); + planTask.setEngineId(""); + planTask.setDeviceId(""); + planTask.setAppId(""); + planTask.setStatus(PlanConstant.TASK_WAIT_EXECUTE_STATUS); + planTask.setStartTime(null); + planTask.setEndTime(null); + planTask.setErrorMsg(""); + planTask.setVideoUrl(""); + planTask.setExecResultFile(""); + planTask.setBugId(""); + if (sceneNodeExecDto != null && sceneNodeExecDto.getSceneScriptUrl() != null) { + planTask.setScriptJson(sceneNodeExecDto.getSceneScriptUrl()); + } else { + logger.info("首节点返回sceneScriptUrl为空" + sceneNodeExecDto); + } + int rows = atuPlanTaskService.updateByPrimaryKey(planTask); + if (rows <= 0) { + throw new PlatformRuntimeException(ExecPlanError.INIT_TASK_INFO_FAIL); + } + + logger.debug("发送任务执行信息至消息队列"); + sendToQueue(taskExecDto.getBatchId(), taskExecDto, type); + + atuPlanInfoApiService.handleAutoType(PlanConstant.SCRIPT_TYPE_SCENE, caseTypeMap); + } + + logger.debug("计划批次重新发起委托"); + atuPlanInfoApiService.handlePlanDevice(planInfo.getId(), planInfo.getPriority(), planBatch.getId(), + retryDto.getHasOfflineDevice(), caseTypeMap, true); + return true; } @Override diff --git a/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/exception/ExecPlanError.java b/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/exception/ExecPlanError.java index 58f5751..ff17a75 100644 --- a/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/exception/ExecPlanError.java +++ b/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/exception/ExecPlanError.java @@ -88,7 +88,7 @@ public enum ExecPlanError implements PlatformError { GET_FILE_FAIL("获取文件失败"), EMPTY_BATCH_ID("批次id不能为空"), - BATCH_IS_DEALING_WITH_RETRY("批次的任务重试正在处理中..."), + BATCH_IS_DEALING_WITH_RETRY("批次信息正在处理中,请稍后尝试操作..."), /** * 错误码结束值 diff --git a/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/job/PlanBatchTaskDataUpdateJob.java b/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/job/PlanBatchTaskDataUpdateJob.java index e3ef07f..fd2bf16 100644 --- a/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/job/PlanBatchTaskDataUpdateJob.java +++ b/cctp-atu/atu-execute-plan/src/main/java/net/northking/cctp/executePlan/job/PlanBatchTaskDataUpdateJob.java @@ -9,6 +9,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import net.northking.cctp.common.enums.FileBusinessTypeEnum; +import net.northking.cctp.common.exception.PlatformRuntimeException; import net.northking.cctp.common.s3.NKFile; import net.northking.cctp.common.s3.SimpleStorageService; import net.northking.cctp.common.security.authentication.NKSecurityContext; @@ -27,6 +28,7 @@ import net.northking.cctp.executePlan.dto.planBatch.*; import net.northking.cctp.executePlan.dto.planInfo.AtuPlanRunDto; import net.northking.cctp.executePlan.dto.planTask.ScriptStatusStatistic; import net.northking.cctp.executePlan.enums.MobilePlatformEnum; +import net.northking.cctp.executePlan.exception.ExecPlanError; import net.northking.cctp.executePlan.feign.PublicFeignClient; import net.northking.cctp.executePlan.utils.MinioPathUtils; import org.redisson.api.RLock; @@ -34,6 +36,7 @@ import org.redisson.api.RedissonClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.amqp.core.AmqpAdmin; +import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.RedisTemplate; @@ -119,6 +122,9 @@ public class PlanBatchTaskDataUpdateJob { @Autowired private RedisLockRegistry redisLockRegistry; + @Autowired + private RabbitTemplate rabbitTemplate; + private final static String LOCK_KEY_BATCH_SUM = "LOCK:PLAN:BATCH-SUM-DATA-UPDATE-METHOD"; private final static String BATCH_IS_NULL_COUNT_HASH = "PLAN:BATCH:NULL-COUNT-HASH"; @@ -165,175 +171,185 @@ public class PlanBatchTaskDataUpdateJob { String batchId = key.substring(key.lastIndexOf(":") + 1); String clusterKeyPrefix = RedisConstant.CLUSTER_KEY_PREFIX + batchId.substring(0, 4) + RedisConstant.CLUSTER_KEY_SUFFIX; - - // 通过数据库进行统计,减少统计数据出错的原因 - AtuPlanBatch batch = this.planBatchService.findByPrimaryKey(batchId); - if (batch == null) { - logger.info("批次【{}】信息目前不存在,再等待下一次查询...", batchId); - Boolean existFlag = redisTemplate.opsForHash().hasKey(BATCH_IS_NULL_COUNT_HASH, batchId); - if (existFlag) { - Object nullCount = redisTemplate.opsForHash().get(BATCH_IS_NULL_COUNT_HASH, batchId); - if (nullCount != null && NumberUtil.isNumber(nullCount.toString())) { - int i = Integer.parseInt(nullCount.toString()); - if (i < 100) { // 统计100次后依然没有批次信息,批次不存在 - redisTemplate.opsForHash().put(BATCH_IS_NULL_COUNT_HASH, batchId, i + 1); - } else { - // 没有对应批次数据,删除缓存数据 - logger.debug("没有对应的批次信息[{}],删除缓存数据", batchId); - redisTemplate.delete(key); - } - } - } else { - redisTemplate.opsForHash().put(BATCH_IS_NULL_COUNT_HASH, batchId, 1); - } - return; // 退出这个批次统计 - } - // 批次信息存在 - AtuPlanTask totalQ = new AtuPlanTask(); - totalQ.setBatchId(batchId); - long currentTaskTotal = planTaskService.count(totalQ); - // 判断批次任务是否已经全部生成 - if (batch.getTaskTotal() > currentTaskTotal) { - logger.info("批次[{}]正在生成任务中,结束统计...", batchId); + Lock batchLock = redisLockRegistry.obtain(String.format("%s%s", RedisConstant.PLAN_BATCH_RETRY_LOCK_PRE, batchId)); + if (!batchLock.tryLock()) { + // 获取不到锁,正在处理重试,此次统计不需要 + logger.info("批次【{}】正在处理任务重试操作,此次统计不需要", batchId); return; } - // 以脚本维度统计批次下各脚本的执行情况 - AtuPlanTask taskQ = new AtuPlanTask(); - taskQ.setBatchId(batchId); - List resultList = planTaskService.countTaskStatus(taskQ); - List batchStatusList = new ArrayList<>(); - for (ScriptStatusStatistic result : resultList) { - Set statusSet = result.getStatusSet(); - result.setStatus(scriptStatus(statusSet)); // 根据脚本下的所有任务确定脚本的执行结果 - batchStatusList.add(result.getStatus()); - } - int allScriptCount = batchStatusList.size(); // 总脚本执行数 - // 等待中 - int waitCount = Collections.frequency(batchStatusList, PlanConstant.TASK_WAIT_EXECUTE_STATUS); - // 执行中 - int ingCount = Collections.frequency(batchStatusList, PlanConstant.TASK_START_EXECUTE_STATUS); - // 成功 - int successCount = Collections.frequency(batchStatusList, PlanConstant.TASK_EXECUTE_SUCCESS_STATUS); - // 执行失败 - int executeFailCount = Collections.frequency(batchStatusList, PlanConstant.TASK_EXECUTE_FAIL_STATUS); - // 断言失败 - int assertFailCount = Collections.frequency(batchStatusList, PlanConstant.TASK_ASSERT_FAIL_STATUS); - // 取消的 - int cancelCount = Collections.frequency(batchStatusList, PlanConstant.TASK_CANCEL_STATUS); - // 超时的 - int timeoutCount = Collections.frequency(batchStatusList, PlanConstant.TASK_TIMEOUT_STATUS); - - if (waitCount > 0 || ingCount > 0) { // 批次还没有完成 - // 检查批次的开始时间 - Date createdTime = batch.getCreatedTime(); - if (createdTime != null) { // 有创建时间,那么比较开始时间与现在的时间差 - LocalDateTime createDateTime = createdTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); - LocalDateTime now = LocalDateTime.now(); - Duration duration = Duration.between(createDateTime, now); - long hours = duration.toHours(); - if (atuPlanConfig.isBatchExecuteTimeoutEnabled() && hours > atuPlanConfig.getBatchExecuteTimeout().longValue()) { // 参数化 - logger.info("批次[{}-{}]已创建{}小时,任务没有执行完成,强制结束批次", batch.getId(), batch.getBatch(), 48); - // 如果批次的创建时间离现在已经过去48小时还没完成,那么判定批次已完成,等待中|执行中 的任务全部算超时处理 - timeoutCount += waitCount; - timeoutCount += ingCount; - waitCount = 0; - ingCount = 0; - // 更新批次下 等待中(0)|执行中(1) 的任务全部算超时处理(6) - this.planTaskService.batchUpdateTaskStatusToTimeout(batch.getId(), PlanConstant.TASK_TIMEOUT_STATUS, PlanConstant.TASK_WAIT_EXECUTE_STATUS, PlanConstant.TASK_START_EXECUTE_STATUS); + try { + // 通过数据库进行统计,减少统计数据出错的原因 + AtuPlanBatch batch = this.planBatchService.findByPrimaryKey(batchId); + if (batch == null) { + logger.info("批次【{}】信息目前不存在,再等待下一次查询...", batchId); + Boolean existFlag = redisTemplate.opsForHash().hasKey(BATCH_IS_NULL_COUNT_HASH, batchId); + if (existFlag) { + Object nullCount = redisTemplate.opsForHash().get(BATCH_IS_NULL_COUNT_HASH, batchId); + if (nullCount != null && NumberUtil.isNumber(nullCount.toString())) { + int i = Integer.parseInt(nullCount.toString()); + if (i < 100) { // 统计100次后依然没有批次信息,批次不存在 + redisTemplate.opsForHash().put(BATCH_IS_NULL_COUNT_HASH, batchId, i + 1); + } else { + // 没有对应批次数据,删除缓存数据 + logger.debug("没有对应的批次信息[{}],删除缓存数据", batchId); + redisTemplate.delete(key); + } + } } else { - // 批次还没有完成,退出统计 - return; + redisTemplate.opsForHash().put(BATCH_IS_NULL_COUNT_HASH, batchId, 1); } - } else { - // 有批次信息,但是没有创建时间,应该是数据有问题 - logger.debug("批次[{}]没有创建时间", batch.getId()); + return; // 退出这个批次统计 + } + // 批次信息存在 + AtuPlanTask totalQ = new AtuPlanTask(); + totalQ.setBatchId(batchId); + long currentTaskTotal = planTaskService.count(totalQ); + // 判断批次任务是否已经全部生成 + if (batch.getTaskTotal() > currentTaskTotal) { + logger.info("批次[{}]正在生成任务中,结束统计...", batchId); return; } - } - // 批次已完成 - - // 更新批次表 - AtuPlanBatch planBatch = new AtuPlanBatch(); - planBatch.setId(batchId); - planBatch.setSuccessNum(successCount); - planBatch.setExecFailNum(executeFailCount); - planBatch.setAssertFailNum(assertFailCount); - planBatch.setTimeoutNum(timeoutCount); - planBatch.setCancelNum(cancelCount); - - planBatch.setSuccessRate(MsgConstant.PLAN_BATCH_SUCCESS_RATE); - if (planBatch.getSuccessNum() > 0 && allScriptCount > 0) { - planBatch.setSuccessRate(NumberUtil.decimalFormat(MsgConstant.PATTERN_HASH_DOT_HASH_HASH, NumberUtil.div(planBatch.getSuccessNum().intValue(), allScriptCount))); - } - // 查询批次最先开始执行的任务的开始时间 - if (planBatch.getStartTime() == null) { - Long firstTaskStartTime = planTaskService.queryBatchFirstTaskStartTime(batchId); - if (ObjectUtil.isNotNull(firstTaskStartTime)) { - planBatch.setStartTime(new Date(firstTaskStartTime)); + // 以脚本维度统计批次下各脚本的执行情况 + AtuPlanTask taskQ = new AtuPlanTask(); + taskQ.setBatchId(batchId); + List resultList = planTaskService.countTaskStatus(taskQ); + List batchStatusList = new ArrayList<>(); + for (ScriptStatusStatistic result : resultList) { + Set statusSet = result.getStatusSet(); + result.setStatus(scriptStatus(statusSet)); // 根据脚本下的所有任务确定脚本的执行结果 + batchStatusList.add(result.getStatus()); } - } - // 任务状态判断 - String planStatus = ""; - if (planBatch.getCancelNum() > 0) { - planStatus = PlanConstant.PLAN_CANCEL_STATUS; - // 修改为取消状态 - planBatch.setStatus(PlanConstant.BATCH_CANCEL_STATUS); - } else { - planStatus = PlanConstant.PLAN_FINISH_STATUS; - // 修改为已完成状态 - planBatch.setStatus(PlanConstant.BATCH_FINISH_STATUS); + int allScriptCount = batchStatusList.size(); // 总脚本执行数 + // 等待中 + int waitCount = Collections.frequency(batchStatusList, PlanConstant.TASK_WAIT_EXECUTE_STATUS); + // 执行中 + int ingCount = Collections.frequency(batchStatusList, PlanConstant.TASK_START_EXECUTE_STATUS); + // 成功 + int successCount = Collections.frequency(batchStatusList, PlanConstant.TASK_EXECUTE_SUCCESS_STATUS); + // 执行失败 + int executeFailCount = Collections.frequency(batchStatusList, PlanConstant.TASK_EXECUTE_FAIL_STATUS); + // 断言失败 + int assertFailCount = Collections.frequency(batchStatusList, PlanConstant.TASK_ASSERT_FAIL_STATUS); + // 取消的 + int cancelCount = Collections.frequency(batchStatusList, PlanConstant.TASK_CANCEL_STATUS); + // 超时的 + int timeoutCount = Collections.frequency(batchStatusList, PlanConstant.TASK_TIMEOUT_STATUS); + + if (waitCount > 0 || ingCount > 0) { // 批次还没有完成 + // 检查批次的开始时间 + Date createdTime = batch.getCreatedTime(); + if (createdTime != null) { // 有创建时间,那么比较开始时间与现在的时间差 + LocalDateTime createDateTime = createdTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + LocalDateTime now = LocalDateTime.now(); + Duration duration = Duration.between(createDateTime, now); + long hours = duration.toHours(); + if (atuPlanConfig.isBatchExecuteTimeoutEnabled() && hours > atuPlanConfig.getBatchExecuteTimeout().longValue()) { // 参数化 + logger.info("批次[{}-{}]已创建{}小时,任务没有执行完成,强制结束批次", batch.getId(), batch.getBatch(), 48); + // 如果批次的创建时间离现在已经过去48小时还没完成,那么判定批次已完成,等待中|执行中 的任务全部算超时处理 + timeoutCount += waitCount; + timeoutCount += ingCount; + waitCount = 0; + ingCount = 0; + // 更新批次下 等待中(0)|执行中(1) 的任务全部算超时处理(6) + this.planTaskService.batchUpdateTaskStatusToTimeout(batch.getId(), PlanConstant.TASK_TIMEOUT_STATUS, PlanConstant.TASK_WAIT_EXECUTE_STATUS, PlanConstant.TASK_START_EXECUTE_STATUS); + } else { + // 批次还没有完成,退出统计 + return; + } + } else { + // 有批次信息,但是没有创建时间,应该是数据有问题 + logger.debug("批次[{}]没有创建时间", batch.getId()); + return; + } + } + // 批次已完成 + + // 更新批次表 + AtuPlanBatch planBatch = new AtuPlanBatch(); + planBatch.setId(batchId); + planBatch.setSuccessNum(successCount); + planBatch.setExecFailNum(executeFailCount); + planBatch.setAssertFailNum(assertFailCount); + planBatch.setTimeoutNum(timeoutCount); + planBatch.setCancelNum(cancelCount); + + planBatch.setSuccessRate(MsgConstant.PLAN_BATCH_SUCCESS_RATE); + if (planBatch.getSuccessNum() > 0 && allScriptCount > 0) { + planBatch.setSuccessRate(NumberUtil.decimalFormat(MsgConstant.PATTERN_HASH_DOT_HASH_HASH, NumberUtil.div(planBatch.getSuccessNum().intValue(), allScriptCount))); + } + // 查询批次最先开始执行的任务的开始时间 + if (planBatch.getStartTime() == null) { + Long firstTaskStartTime = planTaskService.queryBatchFirstTaskStartTime(batchId); + if (ObjectUtil.isNotNull(firstTaskStartTime)) { + planBatch.setStartTime(new Date(firstTaskStartTime)); + } + } + // 任务状态判断 + String planStatus = ""; + if (planBatch.getCancelNum() > 0) { + planStatus = PlanConstant.PLAN_CANCEL_STATUS; + // 修改为取消状态 + planBatch.setStatus(PlanConstant.BATCH_CANCEL_STATUS); + } else { + planStatus = PlanConstant.PLAN_FINISH_STATUS; + // 修改为已完成状态 + planBatch.setStatus(PlanConstant.BATCH_FINISH_STATUS); + } + + // 查询批次最后执行完成的任务的结束时间 + Long lastTaskEndTime = planTaskService.queryBatchLastTaskEndTime(batchId); + if (ObjectUtil.isNotNull(lastTaskEndTime)) { + planBatch.setEndTime(new Date(lastTaskEndTime)); + } + logger.debug("更新批次信息"); + planBatchService.updateByPrimaryKey(planBatch); + + // 删除任务队列 + amqpAdmin.deleteQueue(RabbitConstant.TASK_EXEC_QUEUE_PC_KEY + batchId); + // 移动端删除各个平台对于的队列 + MobilePlatformEnum[] platformEnums = MobilePlatformEnum.values(); + for (MobilePlatformEnum platformEnum : platformEnums) { + amqpAdmin.deleteQueue(RabbitConstant.TASK_EXEC_QUEUE_MOB_KEY + platformEnum.getName() + "." + batchId); + } + amqpAdmin.deleteQueue(RabbitConstant.TASK_EXEC_QUEUE_API_KEY + batchId); + + //获取更新后的批次信息 + AtuPlanBatchDetailDto atuPlanBatchDetailDto = planBatchService.queryBatchDetailById(planBatch.getId()); + + // 判断是否计划最后一批次 + AtuPlanInfo planInfo = planInfoService.queryByLastBatchId(batchId); + if (ObjectUtil.isNotNull(planInfo)) { + // 是则更新计划表 + planInfo.setStatus(planStatus); + planInfo.setWaitingNum(waitCount); + planInfo.setRunningNum(ingCount); + planInfo.setSuccessNum(planBatch.getSuccessNum()); + planInfo.setExecFailNum(planBatch.getExecFailNum()); + planInfo.setAssertFailNum(planBatch.getAssertFailNum()); + planInfo.setTimeoutNum(planBatch.getTimeoutNum()); + planInfo.setCancelNum(planBatch.getCancelNum()); + //不用代码生成的方法 + planInfoService.updatePlanResultById(planInfo); + } + + executor.execute(() -> { + // 保存设备性能数据 + saveDevicePerData(atuPlanBatchDetailDto); + }); + + // 2.2. 删除缓存中已完成批次的记录 + logger.debug("删除批次统计缓存 => " + key); + redisTemplate.delete(key); + + // 收尾处理 + AtuPlanInfo batchPlanInfo = planInfoService.findByBatchId(batchId); + if (batchPlanInfo != null) { + handleEnd(batchPlanInfo, atuPlanBatchDetailDto); + } + } finally { + batchLock.unlock(); } - // 查询批次最后执行完成的任务的结束时间 - Long lastTaskEndTime = planTaskService.queryBatchLastTaskEndTime(batchId); - if (ObjectUtil.isNotNull(lastTaskEndTime)) { - planBatch.setEndTime(new Date(lastTaskEndTime)); - } - logger.debug("更新批次信息"); - planBatchService.updateByPrimaryKey(planBatch); - - // 删除任务队列 - amqpAdmin.deleteQueue(RabbitConstant.TASK_EXEC_QUEUE_PC_KEY + batchId); - // 移动端删除各个平台对于的队列 - MobilePlatformEnum[] platformEnums = MobilePlatformEnum.values(); - for (MobilePlatformEnum platformEnum : platformEnums) { - amqpAdmin.deleteQueue(RabbitConstant.TASK_EXEC_QUEUE_MOB_KEY + platformEnum.getName() + "." + batchId); - } - amqpAdmin.deleteQueue(RabbitConstant.TASK_EXEC_QUEUE_API_KEY + batchId); - - //获取更新后的批次信息 - AtuPlanBatchDetailDto atuPlanBatchDetailDto = planBatchService.queryBatchDetailById(planBatch.getId()); - - // 判断是否计划最后一批次 - AtuPlanInfo planInfo = planInfoService.queryByLastBatchId(batchId); - if (ObjectUtil.isNotNull(planInfo)) { - // 是则更新计划表 - planInfo.setStatus(planStatus); - planInfo.setWaitingNum(waitCount); - planInfo.setRunningNum(ingCount); - planInfo.setSuccessNum(planBatch.getSuccessNum()); - planInfo.setExecFailNum(planBatch.getExecFailNum()); - planInfo.setAssertFailNum(planBatch.getAssertFailNum()); - planInfo.setTimeoutNum(planBatch.getTimeoutNum()); - planInfo.setCancelNum(planBatch.getCancelNum()); - //不用代码生成的方法 - planInfoService.updatePlanResultById(planInfo); - } - - executor.execute(() -> { - // 保存设备性能数据 - saveDevicePerData(atuPlanBatchDetailDto); - }); - - // 2.2. 删除缓存中已完成批次的记录 - logger.debug("删除批次统计缓存 => " + key); - redisTemplate.delete(key); - - // 收尾处理 - AtuPlanInfo batchPlanInfo = planInfoService.findByBatchId(batchId); - if (batchPlanInfo != null) { - handleEnd(batchPlanInfo, atuPlanBatchDetailDto); - } }); logger.debug("同步缓存中计划批次统计数据----end----"); } catch (Exception e) {