diff --git a/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanReportService.java b/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanReportService.java index ef3df2be94..3b2fc1a3ca 100644 --- a/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanReportService.java +++ b/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanReportService.java @@ -65,6 +65,7 @@ import java.util.stream.Collectors; @Transactional(rollbackFor = Exception.class) public class TestPlanReportService { + private final String GROUP = "GROUP"; @Resource TestPlanReportMapper testPlanReportMapper; @Resource @@ -133,8 +134,6 @@ public class TestPlanReportService { @Resource private ExtApiExecutionQueueMapper extApiExecutionQueueMapper; - private final String GROUP = "GROUP"; - //这个方法是消息通知时获取报告内容的。 public List getReports(List reportIdList) { List reportList = new ArrayList<>(); @@ -360,7 +359,7 @@ public class TestPlanReportService { } if (testPlanReport == null) { - if(runInfoDTO == null){ + if (runInfoDTO == null) { runInfoDTO = new TestPlanReportRunInfoDTO(); } if (!saveRequest.isApiCaseIsExecuting() && !saveRequest.isScenarioIsExecuting()) { @@ -1476,9 +1475,58 @@ public class TestPlanReportService { returnMap = apiDefinitionExecResultList.stream().collect(Collectors.toMap(ApiDefinitionExecResult::getId, ApiDefinitionExecResult::getStatus, (k1, k2) -> k1)); } } + this.checkApiCaseAndScenarioRunningResult(returnMap, true); return returnMap; } + //检查是否有未完成的报告。 (由于微服务架构,可能在api服务的事务没有提交,会出现这样的情况) + private void checkApiCaseAndScenarioRunningResult(Map checkMap, boolean isApiCase) { + if (MapUtils.isEmpty(checkMap)) { + return; + } + String checkStatus = "running"; + Map runningReportMap = new HashMap<>(); + for (Map.Entry entry : checkMap.entrySet()) { + if (StringUtils.equalsAnyIgnoreCase(entry.getValue(), checkStatus)) { + runningReportMap.put(entry.getKey(), entry.getValue()); + } + } + //等待sleepSeconds时间api服务的事务来提交。 重复foreachTimes次 + int foreachTimes = 2; + int sleepSeconds = 3000; + + try { + for (int i = 0; i < foreachTimes; i++) { + //延迟3s进行计算(等待事务提交) + Thread.sleep(sleepSeconds); + if (isApiCase) { + List apiDefinitionExecResultList = planTestPlanApiCaseService.selectReportStatusByReportIds(new ArrayList<>(runningReportMap.keySet())); + runningReportMap = new HashMap<>(); + for (ApiDefinitionExecResult result : apiDefinitionExecResultList) { + if (StringUtils.equalsIgnoreCase(result.getStatus(), checkStatus)) { + runningReportMap.put(result.getId(), result.getStatus()); + } else { + checkMap.put(result.getId(), result.getStatus()); + } + } + } else { + List scenarioReportList = planTestPlanScenarioCaseService.selectReportStatusByReportIds(new ArrayList<>(runningReportMap.keySet())); + runningReportMap = new HashMap<>(); + for (ApiScenarioReport result : scenarioReportList) { + if (StringUtils.equalsIgnoreCase(result.getStatus(), checkStatus)) { + runningReportMap.put(result.getId(), result.getStatus()); + } else { + checkMap.put(result.getId(), result.getStatus()); + } + } + } + } + } catch (Exception e) { + LogUtil.error("用例报告重新查询报错", e); + } + } + + private Map selectScenarioRunResultByIds(List scenarioReportIdList) { Map returnMap = new HashMap<>(); if (CollectionUtils.isNotEmpty(scenarioReportIdList)) { @@ -1487,6 +1535,7 @@ public class TestPlanReportService { returnMap = apiDefinitionExecResultList.stream().collect(Collectors.toMap(ApiScenarioReport::getId, ApiScenarioReport::getStatus, (k1, k2) -> k1)); } } + this.checkApiCaseAndScenarioRunningResult(returnMap, false); return returnMap; } diff --git a/test-track/backend/src/main/java/io/metersphere/plan/service/remote/api/PlanTestPlanApiCaseService.java b/test-track/backend/src/main/java/io/metersphere/plan/service/remote/api/PlanTestPlanApiCaseService.java index f2331214de..ff00a8b0ee 100644 --- a/test-track/backend/src/main/java/io/metersphere/plan/service/remote/api/PlanTestPlanApiCaseService.java +++ b/test-track/backend/src/main/java/io/metersphere/plan/service/remote/api/PlanTestPlanApiCaseService.java @@ -1,6 +1,8 @@ package io.metersphere.plan.service.remote.api; +import io.metersphere.base.domain.ApiDefinitionExecResult; import io.metersphere.base.domain.ApiDefinitionExecResultWithBLOBs; +import io.metersphere.base.mapper.ext.ExtTestPlanApiCaseMapper; import io.metersphere.commons.constants.MicroServiceName; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.LogUtil; @@ -11,7 +13,6 @@ import io.metersphere.plan.request.api.ApiTestCaseRequest; import io.metersphere.plan.service.TestPlanService; import io.metersphere.plan.utils.TestPlanReportUtil; import io.metersphere.plan.utils.TestPlanStatusCalculator; -import io.metersphere.utils.BatchProcessingUtil; import io.metersphere.utils.DiscoveryUtil; import jakarta.annotation.Resource; import org.apache.commons.collections.CollectionUtils; @@ -31,6 +32,8 @@ public class PlanTestPlanApiCaseService extends ApiTestService { @Resource PlanApiDefinitionExecResultService planApiDefinitionExecResultService; @Resource + ExtTestPlanApiCaseMapper extTestPlanApiCaseMapper; + @Resource @Lazy TestPlanService testPlanService; @@ -200,4 +203,11 @@ public class PlanTestPlanApiCaseService extends ApiTestService { return microService.getForDataArray(serviceName, BASE_UEL + "/get/report/ext/" + planId, ApiDefinitionExecResultWithBLOBs.class); } + @Transactional(propagation = Propagation.REQUIRES_NEW) + public List selectReportStatusByReportIds(List reportIds) { + if (CollectionUtils.isEmpty(reportIds)) { + return new ArrayList<>(); + } + return extTestPlanApiCaseMapper.selectReportStatusByReportIds(reportIds); + } } diff --git a/test-track/backend/src/main/java/io/metersphere/plan/service/remote/api/PlanTestPlanScenarioCaseService.java b/test-track/backend/src/main/java/io/metersphere/plan/service/remote/api/PlanTestPlanScenarioCaseService.java index 751ee7cf05..909aaefbb4 100644 --- a/test-track/backend/src/main/java/io/metersphere/plan/service/remote/api/PlanTestPlanScenarioCaseService.java +++ b/test-track/backend/src/main/java/io/metersphere/plan/service/remote/api/PlanTestPlanScenarioCaseService.java @@ -1,6 +1,8 @@ package io.metersphere.plan.service.remote.api; +import io.metersphere.base.domain.ApiScenarioReport; import io.metersphere.base.domain.TestPlanReport; +import io.metersphere.base.mapper.ext.ExtTestPlanScenarioCaseMapper; import io.metersphere.commons.constants.MicroServiceName; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.LogUtil; @@ -19,6 +21,8 @@ import org.apache.commons.collections.CollectionUtils; import org.jetbrains.annotations.NotNull; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.util.stream.Collectors; @@ -34,6 +38,8 @@ public class PlanTestPlanScenarioCaseService extends ApiTestService { @Resource PlanApiScenarioReportService planApiScenarioReportService; + @Resource + ExtTestPlanScenarioCaseMapper extTestPlanScenarioCaseMapper; public void calculatePlanReport(String planId, TestPlanReportDataStruct report) { if (DiscoveryUtil.hasService(MicroServiceName.API_TEST)) { @@ -212,4 +218,12 @@ public class PlanTestPlanScenarioCaseService extends ApiTestService { request.setAllowedRepeatCase(testPlanService.isAllowedRepeatCase(request.getPlanId())); return microService.postForData(serviceName, BASE_UEL + String.format("/relevance/list/%s/%s", pageNum, pageSize), request); } + + @Transactional(propagation = Propagation.REQUIRES_NEW) + public List selectReportStatusByReportIds(List reportIds) { + if (CollectionUtils.isEmpty(reportIds)) { + return new ArrayList<>(); + } + return extTestPlanScenarioCaseMapper.selectReportStatusByReportIds(reportIds); + } }