diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java index a53fef875e..c64b66b22d 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java @@ -1,7 +1,6 @@ package io.metersphere.api.dto.definition.request.sampler; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; @@ -225,16 +224,14 @@ public class MsHTTPSamplerProxy extends MsTestElement { setSamplerPath(config, httpConfig, sampler); - // 请求体 - if (!StringUtils.equals(this.getMethod(), "GET")) { - if (this.body != null) { - List bodyParams = this.body.getBodyParams(sampler, this.getId()); - if (StringUtils.isNotEmpty(this.body.getType()) && "Form Data".equals(this.body.getType())) { - sampler.setDoMultipart(true); - } - if (CollectionUtils.isNotEmpty(bodyParams)) { - sampler.setArguments(httpArguments(bodyParams)); - } + // 请求体处理 + if (this.body != null) { + List bodyParams = this.body.getBodyParams(sampler, this.getId()); + if (StringUtils.isNotEmpty(this.body.getType()) && "Form Data".equals(this.body.getType())) { + sampler.setDoMultipart(true); + } + if (CollectionUtils.isNotEmpty(bodyParams)) { + sampler.setArguments(httpArguments(bodyParams)); } } diff --git a/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerHandler.java b/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerHandler.java index 4b14129810..c5c7c237d7 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerHandler.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerHandler.java @@ -56,5 +56,8 @@ public class APIBackendListenerHandler { if (!MessageCache.reportCache.containsKey(testId) && resultService.getProcessCache().containsKey(testId)) { resultService.getProcessCache().remove(testId); } + if(StringUtils.isNotEmpty(testId)) { + MessageCache.executionQueue.remove(testId); + } } } diff --git a/backend/src/main/java/io/metersphere/api/jmeter/MessageCache.java b/backend/src/main/java/io/metersphere/api/jmeter/MessageCache.java index 73bec5fcae..47bd821598 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/MessageCache.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/MessageCache.java @@ -20,4 +20,7 @@ public class MessageCache { public static ConcurrentHashMap batchTestCases = new ConcurrentHashMap<>(); + // 串行执行队列 KEY=报告ID VALUE=开始时间 + public static Map executionQueue = new HashMap<>(); + } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java index 3d99d21904..1b5821ff6a 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -51,7 +51,9 @@ import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; import io.metersphere.track.request.testcase.QueryTestPlanRequest; import io.metersphere.track.request.testplan.FileOperationRequest; import io.metersphere.track.service.TestPlanScenarioCaseService; +import org.apache.commons.beanutils.BeanComparator; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.comparators.FixedOrderComparator; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.session.ExecutorType; @@ -997,11 +999,19 @@ public class ApiAutomationService { // 生成集成报告 String serialReportId = null; - StringBuilder idStr = new StringBuilder(); - ids.forEach(item -> { - idStr.append("\"").append(item).append("\"").append(","); - }); - List apiScenarios = extApiScenarioMapper.selectByIds(idStr.toString().substring(0, idStr.toString().length() - 1), "\"" + StringUtils.join(ids, ",") + "\""); + ApiScenarioExample example = new ApiScenarioExample(); + example.createCriteria().andIdIn(ids); + List apiScenarios = apiScenarioMapper.selectByExampleWithBLOBs(example); + if (request.getConfig() != null && request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) { + if (request.getCondition() == null || !request.getCondition().isSelectAll()) { + // 按照id指定顺序排序 + FixedOrderComparator fixedOrderComparator = new FixedOrderComparator(ids); + fixedOrderComparator.setUnknownObjectBehavior(FixedOrderComparator.UnknownObjectBehavior.BEFORE); + BeanComparator beanComparator = new BeanComparator("id", fixedOrderComparator); + Collections.sort(apiScenarios, beanComparator); + } + } + // 只有一个场景且没有测试步骤,则提示 if (apiScenarios != null && apiScenarios.size() == 1 && (apiScenarios.get(0).getStepTotal() == null || apiScenarios.get(0).getStepTotal() == 0)) { MSException.throwException((apiScenarios.get(0).getName() + "," + Translator.get("automation_exec_info"))); @@ -1162,6 +1172,7 @@ public class ApiAutomationService { MessageCache.terminationOrderDeque.remove(key); break; } + MessageCache.executionQueue.put(key, System.currentTimeMillis()); reportIds.add(key); APIScenarioReportResult report = executeQueue.get(key).getReport(); if (StringUtils.isNotEmpty(serialReportId)) { @@ -1193,6 +1204,7 @@ public class ApiAutomationService { executeEnvParams = hashTreeUtil.mergeParamDataMap(executeEnvParams, envParamsMap); } catch (Exception e) { reportIds.remove(key); + MessageCache.executionQueue.remove(key); LogUtil.error("执行终止:" + e.getMessage()); break; } diff --git a/backend/src/main/java/io/metersphere/api/service/task/SerialScenarioExecTask.java b/backend/src/main/java/io/metersphere/api/service/task/SerialScenarioExecTask.java index 0151101252..8d2825d347 100644 --- a/backend/src/main/java/io/metersphere/api/service/task/SerialScenarioExecTask.java +++ b/backend/src/main/java/io/metersphere/api/service/task/SerialScenarioExecTask.java @@ -34,7 +34,7 @@ public class SerialScenarioExecTask implements Callable { @Override public T call() { try { - if (runModeDataDTO.getReport()!=null && MessageCache.terminationOrderDeque.contains(runModeDataDTO.getReport().getId())) { + if (runModeDataDTO.getReport() != null && MessageCache.terminationOrderDeque.contains(runModeDataDTO.getReport().getId())) { MessageCache.terminationOrderDeque.remove(runModeDataDTO.getReport().getId()); return null; } @@ -43,25 +43,24 @@ public class SerialScenarioExecTask implements Callable { } else { jMeterService.runLocal(runModeDataDTO.getReport().getId(), runModeDataDTO.getHashTree(), TriggerMode.BATCH.name().equals(request.getTriggerMode()) ? TriggerMode.BATCH.name() : request.getReportId(), request.getRunMode()); } - // 轮询查看报告状态,最多200次,防止死循环 - int index = 1; - while (index < 200) { - Thread.sleep(3000); - index++; - report = apiScenarioReportMapper.selectByPrimaryKey(runModeDataDTO.getReport().getId()); - if (report != null && !report.getStatus().equals(APITestStatus.Running.name())) { + while (MessageCache.executionQueue.containsKey(runModeDataDTO.getReport().getId())) { + long currentSecond = (System.currentTimeMillis() - MessageCache.executionQueue.get(runModeDataDTO.getReport().getId())) / 1000 / 60; + // 设置五分钟超时 + if (currentSecond > 5) { + // 执行失败了,恢复报告状态 + report = apiScenarioReportMapper.selectByPrimaryKey(runModeDataDTO.getReport().getId()); + if (report != null) { + report.setStatus(APITestStatus.Error.name()); + apiScenarioReportMapper.updateByPrimaryKey(report); + } break; } - if (runModeDataDTO.getReport()!=null && MessageCache.terminationOrderDeque.contains(runModeDataDTO.getReport().getId())) { + if (runModeDataDTO.getReport() != null && MessageCache.terminationOrderDeque.contains(runModeDataDTO.getReport().getId())) { MessageCache.terminationOrderDeque.remove(runModeDataDTO.getReport().getId()); break; } } - // 执行失败了,恢复报告状态 - if (index == 200 && report != null && report.getStatus().equals(APITestStatus.Running.name())) { - report.setStatus(APITestStatus.Error.name()); - apiScenarioReportMapper.updateByPrimaryKey(report); - } + report = apiScenarioReportMapper.selectByPrimaryKey(runModeDataDTO.getReport().getId()); return (T) report; } catch (Exception ex) { LogUtil.error(ex);