From 27188fe5fe9d5e09e89e1a7901805376d7f56793 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Tue, 24 May 2022 15:25:06 +0800 Subject: [PATCH] =?UTF-8?q?feat(UI=E8=87=AA=E5=8A=A8=E5=8C=96):=20UI?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E6=89=B9=E9=87=8F=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../metersphere/api/dto/RunModeDataDTO.java | 2 + .../api/dto/UiExecutionQueueParam.java | 9 ++ .../scenario/ApiScenarioExecuteService.java | 130 +++++++++++------- .../scenario/ApiScenarioParallelService.java | 34 +++-- .../scenario/ApiScenarioSerialService.java | 54 +++++--- .../api/exec/utils/GenerateHashTreeUtil.java | 22 ++- .../metersphere/api/jmeter/JMeterService.java | 10 -- .../api/service/ApiExecutionQueueService.java | 49 ++++--- .../ApiScenarioReportStructureService.java | 2 +- .../api/service/RemakeReportService.java | 10 +- .../api/service/UiReportServiceProxy.java | 11 +- .../service/UiScenarioSerialServiceProxy.java | 31 +++++ .../commons/utils/CommonBeanFactory.java | 13 ++ 13 files changed, 246 insertions(+), 131 deletions(-) create mode 100644 backend/src/main/java/io/metersphere/api/dto/UiExecutionQueueParam.java create mode 100644 backend/src/main/java/io/metersphere/api/service/UiScenarioSerialServiceProxy.java diff --git a/backend/src/main/java/io/metersphere/api/dto/RunModeDataDTO.java b/backend/src/main/java/io/metersphere/api/dto/RunModeDataDTO.java index 58cf6ccd09..f4491821b0 100644 --- a/backend/src/main/java/io/metersphere/api/dto/RunModeDataDTO.java +++ b/backend/src/main/java/io/metersphere/api/dto/RunModeDataDTO.java @@ -2,6 +2,7 @@ package io.metersphere.api.dto; import io.metersphere.api.dto.automation.APIScenarioReportResult; import io.metersphere.base.domain.ApiScenarioWithBLOBs; +import io.metersphere.base.domain.UiScenarioWithBLOBs; import lombok.Getter; import lombok.Setter; @@ -12,6 +13,7 @@ import java.util.Map; public class RunModeDataDTO { // 执行HashTree private ApiScenarioWithBLOBs scenario; + private UiScenarioWithBLOBs uiScenario; // 测试场景/测试用例 private String testId; diff --git a/backend/src/main/java/io/metersphere/api/dto/UiExecutionQueueParam.java b/backend/src/main/java/io/metersphere/api/dto/UiExecutionQueueParam.java new file mode 100644 index 0000000000..243b0694ee --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/UiExecutionQueueParam.java @@ -0,0 +1,9 @@ +package io.metersphere.api.dto; + +import lombok.Data; + +@Data +public class UiExecutionQueueParam { + private String browser; + private Boolean headlessEnabled = false; +} diff --git a/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioExecuteService.java b/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioExecuteService.java index 749354ad84..86338dc35c 100644 --- a/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioExecuteService.java +++ b/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioExecuteService.java @@ -46,6 +46,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.jorphan.collections.HashTree; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; @@ -54,36 +55,37 @@ import java.util.function.Function; import java.util.stream.Collectors; @Service +@Transactional(rollbackFor = Exception.class) public class ApiScenarioExecuteService { @Resource private ApiScenarioEnvService apiScenarioEnvService; @Resource private ApiScenarioMapper apiScenarioMapper; @Resource - private ApiExecutionQueueService apiExecutionQueueService; + protected ApiExecutionQueueService apiExecutionQueueService; @Resource private ExtApiScenarioMapper extApiScenarioMapper; @Resource private TestPlanApiScenarioMapper testPlanApiScenarioMapper; @Resource - private ApiScenarioReportMapper apiScenarioReportMapper; + protected ApiScenarioReportMapper apiScenarioReportMapper; @Resource @Lazy private TestPlanScenarioCaseService testPlanScenarioCaseService; @Resource - private ApiScenarioReportService apiScenarioReportService; + protected ApiScenarioReportService apiScenarioReportService; @Resource private EnvironmentGroupProjectService environmentGroupProjectService; @Resource - private ApiScenarioReportStructureService reportStructureService; + private ApiScenarioReportStructureService apiScenarioReportStructureService; @Resource - private ApiScenarioSerialService serialService; + private ApiScenarioSerialService apiScenarioSerialService; @Resource - private ApiScenarioParallelService parallelService; + private ApiScenarioParallelService apiScenarioParallelService; @Resource private TcpApiParamService tcpApiParamService; @Resource - private JMeterService jMeterService; + protected JMeterService jMeterService; public List run(RunScenarioRequest request) { if (LoggerUtil.getLogger().isDebugEnabled()) { @@ -112,9 +114,8 @@ public class ApiScenarioExecuteService { LoggerUtil.info("Scenario run-执行脚本装载-开始针对所有执行场景进行环境检查"); apiScenarioEnvService.checkEnv(request, apiScenarios); // 集合报告设置 - if (!request.isRerun() && StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString()) - && StringUtils.isNotEmpty(request.getConfig().getReportName())) { - if (request.getConfig().getMode().equals(RunModeConstants.SERIAL.toString())) { + if (!request.isRerun() && GenerateHashTreeUtil.isSetReport(request.getConfig())) { + if (isSerial(request)) { request.setExecuteType(ExecuteType.Completed.name()); } else { request.setExecuteType(ExecuteType.Marge.name()); @@ -151,25 +152,15 @@ public class ApiScenarioExecuteService { } else { LoggerUtil.info("Scenario run-执行脚本装载-初始化集成报告:" + serialReportId); request.getConfig().setReportId(UUID.randomUUID().toString()); + String reportScenarioIds = generateScenarioIds(scenarioIds); - String reportScenarioIds = JSON.toJSONString(CollectionUtils.isNotEmpty(scenarioIds) && scenarioIds.size() > 50 ? scenarioIds.subList(0, 50) : scenarioIds); - APIScenarioReportResult report = apiScenarioReportService.init(request.getConfig().getReportId(), reportScenarioIds, - scenarioNames.toString(), request.getTriggerMode(), ExecuteType.Saved.name(), request.getProjectId(), - request.getReportUserID(), request.getConfig()); - + APIScenarioReportResult report = getApiScenarioReportResult(request, serialReportId, scenarioNames, reportScenarioIds); report.setVersionId(apiScenarios.get(0).getVersionId()); - report.setName(request.getConfig().getReportName()); - report.setId(serialReportId); - report.setReportType(ReportTypeConstants.SCENARIO_INTEGRATED.name()); - request.getConfig().setAmassReport(serialReportId); - if (request.getConfig() != null) { - report.setEnvConfig(JSON.toJSONString(request.getConfig())); - } - report.setStatus(APITestStatus.Running.name()); + apiScenarioReportMapper.insert(report); responseDTOS.add(new MsExecResponseDTO(JSON.toJSONString(scenarioIds), serialReportId, request.getRunMode())); - reportStructureService.save(apiScenarios, serialReportId, request.getConfig().getReportType()); + apiScenarioReportStructureService.save(apiScenarios, serialReportId, request.getConfig().getReportType()); } } @@ -184,21 +175,49 @@ public class ApiScenarioExecuteService { apiScenarioReportService.batchSave(executeQueue, serialReportId, request.getRunMode(), responseDTOS); } // 开始执行 + execute(request, serialReportId, executeQueue, executionQueue); + + return responseDTOS; + } + + protected void execute(RunScenarioRequest request, String serialReportId, Map executeQueue, DBTestQueue executionQueue) { String finalSerialReportId = serialReportId; - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - Thread.currentThread().setName("SCENARIO-PARALLEL-THREAD"); - if (StringUtils.equals(request.getConfig().getMode(), RunModeConstants.SERIAL.toString())) { - serialService.serial(executionQueue, executionQueue.getQueue()); - } else { - parallelService.parallel(executeQueue, request, finalSerialReportId, executionQueue); - } + Thread thread = new Thread(() -> + { + Thread.currentThread().setName("SCENARIO-PARALLEL-THREAD"); + if (isSerial(request)) { + apiScenarioSerialService.serial(executionQueue, executionQueue.getQueue()); + } else { + apiScenarioParallelService.parallel(executeQueue, request, finalSerialReportId, executionQueue); } }); thread.start(); + } - return responseDTOS; + protected boolean isSerial(RunScenarioRequest request) { + return request.getConfig() != null && + StringUtils.equals(request.getConfig().getMode(), RunModeConstants.SERIAL.toString()); + } + + + protected String generateScenarioIds(List scenarioIds) { + return JSON.toJSONString(CollectionUtils.isNotEmpty(scenarioIds) && scenarioIds.size() > 50 ? scenarioIds.subList(0, 50) : scenarioIds); + } + + protected APIScenarioReportResult getApiScenarioReportResult(RunScenarioRequest request, String serialReportId, + StringBuilder scenarioNames, String reportScenarioIds) { + APIScenarioReportResult report = apiScenarioReportService.init(request.getConfig().getReportId(), reportScenarioIds, + scenarioNames.toString(), request.getTriggerMode(), ExecuteType.Saved.name(), request.getProjectId(), + request.getReportUserID(), request.getConfig()); + report.setName(request.getConfig().getReportName()); + report.setId(serialReportId); + report.setReportType(ReportTypeConstants.SCENARIO_INTEGRATED.name()); + request.getConfig().setAmassReport(serialReportId); + if (request.getConfig() != null) { + report.setEnvConfig(JSON.toJSONString(request.getConfig())); + } + report.setStatus(APITestStatus.Running.name()); + return report; } public List get(RunScenarioRequest request) { @@ -208,18 +227,22 @@ public class ApiScenarioExecuteService { 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 (isSerial(request)) { 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); + sortById(ids, apiScenarios); } } return apiScenarios; } + protected void sortById(List ids, List apiScenarios) { + FixedOrderComparator fixedOrderComparator = new FixedOrderComparator(ids); + fixedOrderComparator.setUnknownObjectBehavior(FixedOrderComparator.UnknownObjectBehavior.BEFORE); + BeanComparator beanComparator = new BeanComparator("id", fixedOrderComparator); + Collections.sort(apiScenarios, beanComparator); + } + /** * 测试计划接口场景的预执行(生成场景报告) @@ -283,7 +306,7 @@ public class ApiScenarioExecuteService { } // 生成文档结构 if (!StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())) { - reportStructureService.save(scenario, report.getId(), request.getConfig() != null ? request.getConfig().getReportType() : null); + apiScenarioReportStructureService.save(scenario, report.getId(), request.getConfig() != null ? request.getConfig().getReportType() : null); } // 重置报告ID reportId = UUID.randomUUID().toString(); @@ -306,26 +329,31 @@ public class ApiScenarioExecuteService { report.setVersionId(item.getVersionId()); scenarioNames.append(item.getName()).append(","); - RunModeDataDTO runModeDataDTO = new RunModeDataDTO(); - runModeDataDTO.setTestId(item.getId()); - runModeDataDTO.setPlanEnvMap(new HashMap<>()); + RunModeDataDTO runModeDataDTO = getRunModeDataDTO(item.getId(), report); + runModeDataDTO.setScenario(item); if (request.getConfig().getEnvMap() != null) { runModeDataDTO.setPlanEnvMap(request.getConfig().getEnvMap()); } - runModeDataDTO.setReport(report); - runModeDataDTO.setReportId(report.getId()); - executeQueue.put(report.getId(), runModeDataDTO); - runModeDataDTO.setScenario(item); + executeQueue.put(report.getId(), runModeDataDTO); // 生成报告结构 - if (!StringUtils.equals(request.getConfig().getReportType(), RunModeConstants.SET_REPORT.toString())) { - reportStructureService.save(item, report.getId(), request.getConfig().getReportType()); + if (!GenerateHashTreeUtil.isSetReport(request.getConfig())) { + apiScenarioReportStructureService.save(item, report.getId(), request.getConfig().getReportType()); } // 重置报告ID reportId = UUID.randomUUID().toString(); } } + protected RunModeDataDTO getRunModeDataDTO(String id, APIScenarioReportResult report) { + RunModeDataDTO runModeDataDTO = new RunModeDataDTO(); + runModeDataDTO.setTestId(id); + runModeDataDTO.setPlanEnvMap(new HashMap<>()); + runModeDataDTO.setReport(report); + runModeDataDTO.setReportId(report.getId()); + return runModeDataDTO; + } + public void testElement(RunDefinitionRequest request) { if (request.getTestElement() != null) { tcpApiParamService.checkTestElement(request.getTestElement()); @@ -370,7 +398,7 @@ public class ApiScenarioExecuteService { report.setVersionId(scenario.getVersionId()); String scenarioDefinition = JSON.toJSONString(request.getTestElement().getHashTree().get(0).getHashTree().get(0)); scenario.setScenarioDefinition(scenarioDefinition); - reportStructureService.save(scenario, report.getId(), reportType); + apiScenarioReportStructureService.save(scenario, report.getId(), reportType); } else { if (request.getTestElement() != null && CollectionUtils.isNotEmpty(request.getTestElement().getHashTree())) { ApiScenarioWithBLOBs apiScenario = new ApiScenarioWithBLOBs(); @@ -379,7 +407,7 @@ public class ApiScenarioExecuteService { if (testElement != null) { apiScenario.setName(testElement.getName()); apiScenario.setScenarioDefinition(JSON.toJSONString(testElement)); - reportStructureService.save(apiScenario, report.getId(), reportType); + apiScenarioReportStructureService.save(apiScenario, report.getId(), reportType); } } } diff --git a/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioParallelService.java b/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioParallelService.java index 995e914822..cdcb1f61a1 100644 --- a/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioParallelService.java +++ b/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioParallelService.java @@ -6,7 +6,6 @@ import io.metersphere.api.exec.queue.DBTestQueue; import io.metersphere.api.exec.utils.GenerateHashTreeUtil; import io.metersphere.api.jmeter.JMeterService; import io.metersphere.api.jmeter.utils.SmoothWeighted; -import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.constants.RunModeConstants; import io.metersphere.dto.BaseSystemConfigDTO; import io.metersphere.dto.JmeterRunRequestDTO; @@ -16,16 +15,20 @@ import io.metersphere.vo.BooleanPool; import org.apache.commons.lang3.StringUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.Map; @Service +@Transactional(rollbackFor = Exception.class) public class ApiScenarioParallelService { @Resource - private JMeterService jMeterService; + protected JMeterService jMeterService; @Resource - private RedisTemplate redisTemplate; + protected SystemParameterService systemParameterService; + @Resource + protected RedisTemplate redisTemplate; public void parallel(Map executeQueue, RunScenarioRequest request, String serialReportId, DBTestQueue executionQueue) { // 初始化分配策略 @@ -34,24 +37,16 @@ public class ApiScenarioParallelService { SmoothWeighted.setServerConfig(request.getConfig().getResourcePoolId(), redisTemplate); } // 获取可以执行的资源池 - BaseSystemConfigDTO baseInfo = CommonBeanFactory.getBean(SystemParameterService.class).getBaseInfo(); + BaseSystemConfigDTO baseInfo = systemParameterService.getBaseInfo(); for (String reportId : executeQueue.keySet()) { if (Thread.currentThread().isInterrupted()) { break; } RunModeDataDTO dataDTO = executeQueue.get(reportId); - JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(dataDTO.getTestId(), StringUtils.isNotEmpty(serialReportId) ? serialReportId : reportId, request.getRunMode(), null); - runRequest.setReportType(StringUtils.isNotEmpty(serialReportId) ? RunModeConstants.SET_REPORT.toString() : RunModeConstants.INDEPENDENCE.toString()); - runRequest.setQueueId(executionQueue.getId()); - + JmeterRunRequestDTO runRequest = getJmeterRunRequestDTO(request, serialReportId, executionQueue, baseInfo, reportId, dataDTO); runRequest.setPool(pool); runRequest.setPoolId(request.getConfig().getResourcePoolId()); - runRequest.setTestPlanReportId(request.getTestPlanReportId()); - runRequest.setPlatformUrl(GenerateHashTreeUtil.getPlatformUrl(baseInfo, runRequest, executionQueue.getDetailMap().get(reportId))); - runRequest.setRunType(RunModeConstants.PARALLEL.toString()); - runRequest.setRetryNum(request.getConfig().getRetryNum()); - runRequest.setRetryEnable(request.getConfig().isRetryEnable()); // 本地执行生成hashTree if (!pool.isPool()) { runRequest.setHashTree(GenerateHashTreeUtil.generateHashTree(dataDTO.getScenario(), dataDTO.getPlanEnvMap(), runRequest)); @@ -60,4 +55,17 @@ public class ApiScenarioParallelService { jMeterService.run(runRequest); } } + + protected JmeterRunRequestDTO getJmeterRunRequestDTO(RunScenarioRequest request, String serialReportId, DBTestQueue executionQueue, + BaseSystemConfigDTO baseInfo, String reportId, RunModeDataDTO dataDTO) { + JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(dataDTO.getTestId(), StringUtils.isNotEmpty(serialReportId) ? serialReportId : reportId, request.getRunMode(), null); + runRequest.setReportType(StringUtils.isNotEmpty(serialReportId) ? RunModeConstants.SET_REPORT.toString() : RunModeConstants.INDEPENDENCE.toString()); + runRequest.setQueueId(executionQueue.getId()); + runRequest.setTestPlanReportId(request.getTestPlanReportId()); + runRequest.setPlatformUrl(GenerateHashTreeUtil.getPlatformUrl(baseInfo, runRequest, executionQueue.getDetailMap().get(reportId))); + runRequest.setRunType(RunModeConstants.PARALLEL.toString()); + runRequest.setRetryNum(request.getConfig().getRetryNum()); + runRequest.setRetryEnable(request.getConfig().isRetryEnable()); + return runRequest; + } } diff --git a/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioSerialService.java b/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioSerialService.java index 86deac34ed..8f3ebb3ff8 100644 --- a/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioSerialService.java +++ b/backend/src/main/java/io/metersphere/api/exec/scenario/ApiScenarioSerialService.java @@ -39,6 +39,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.jorphan.collections.HashTree; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.HashMap; @@ -47,6 +48,7 @@ import java.util.LinkedList; import java.util.Map; @Service +@Transactional(rollbackFor = Exception.class) public class ApiScenarioSerialService { @Resource private ApiScenarioReportMapper apiScenarioReportMapper; @@ -80,31 +82,12 @@ public class ApiScenarioSerialService { runRequest.setRetryEnable(queue.getRetryEnable() == null ? false : queue.getRetryEnable()); runRequest.setRetryNum(queue.getRetryNumber()); // 判断触发资源对象是用例/场景更新对应报告状态 - if (!StringUtils.equals(executionQueue.getReportType(), RunModeConstants.SET_REPORT.toString()) + if (!GenerateHashTreeUtil.isSetReport(executionQueue.getReportType()) || StringUtils.equalsIgnoreCase(executionQueue.getRunMode(), ApiRunMode.DEFINITION.name())) { if (StringUtils.equalsAny(executionQueue.getRunMode(), ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) { - ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(queue.getReportId()); - if (report != null) { - report.setStatus(APITestStatus.Running.name()); - report.setCreateTime(System.currentTimeMillis()); - report.setUpdateTime(System.currentTimeMillis()); - runRequest.setExtendedParameters(new HashMap() {{ - this.put("userId", report.getCreateUser()); - }}); - apiScenarioReportMapper.updateByPrimaryKey(report); - LoggerUtil.info("进入串行模式,准备执行资源:[ " + report.getName() + " ], 报告ID [ " + report.getId() + " ]"); - } + updateReportToRunning(queue, runRequest); } else { - ApiDefinitionExecResultWithBLOBs execResult = apiDefinitionExecResultMapper.selectByPrimaryKey(queue.getReportId()); - if (execResult != null) { - runRequest.setExtendedParameters(new HashMap() {{ - this.put("userId", execResult.getUserId()); - }}); - execResult.setStartTime(System.currentTimeMillis()); - execResult.setStatus(APITestStatus.Running.name()); - apiDefinitionExecResultMapper.updateByPrimaryKeySelective(execResult); - LoggerUtil.info("进入串行模式,准备执行资源:[" + execResult.getName() + " ], 报告ID [" + execResult.getId() + "]"); - } + updateDefinitionExecResultToRunning(queue, runRequest); } } @@ -166,6 +149,33 @@ public class ApiScenarioSerialService { } } + protected void updateDefinitionExecResultToRunning(ApiExecutionQueueDetail queue, JmeterRunRequestDTO runRequest) { + ApiDefinitionExecResultWithBLOBs execResult = apiDefinitionExecResultMapper.selectByPrimaryKey(queue.getReportId()); + if (execResult != null) { + runRequest.setExtendedParameters(new HashMap() {{ + this.put("userId", execResult.getUserId()); + }}); + execResult.setStartTime(System.currentTimeMillis()); + execResult.setStatus(APITestStatus.Running.name()); + apiDefinitionExecResultMapper.updateByPrimaryKeySelective(execResult); + LoggerUtil.info("进入串行模式,准备执行资源:[" + execResult.getName() + " ], 报告ID [" + execResult.getId() + "]"); + } + } + + public void updateReportToRunning(ApiExecutionQueueDetail queue, JmeterRunRequestDTO runRequest) { + ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(queue.getReportId()); + if (report != null) { + report.setStatus(APITestStatus.Running.name()); + report.setCreateTime(System.currentTimeMillis()); + report.setUpdateTime(System.currentTimeMillis()); + runRequest.setExtendedParameters(new HashMap() {{ + this.put("userId", report.getCreateUser()); + }}); + apiScenarioReportMapper.updateByPrimaryKey(report); + LoggerUtil.info("进入串行模式,准备执行资源:[ " + report.getName() + " ], 报告ID [ " + report.getId() + " ]"); + } + } + private void initEnv(HashTree hashTree) { ApiTestEnvironmentService apiTestEnvironmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class); HashTreeUtil hashTreeUtil = new HashTreeUtil(); diff --git a/backend/src/main/java/io/metersphere/api/exec/utils/GenerateHashTreeUtil.java b/backend/src/main/java/io/metersphere/api/exec/utils/GenerateHashTreeUtil.java index d22d7e435b..0681ae2586 100644 --- a/backend/src/main/java/io/metersphere/api/exec/utils/GenerateHashTreeUtil.java +++ b/backend/src/main/java/io/metersphere/api/exec/utils/GenerateHashTreeUtil.java @@ -154,11 +154,7 @@ public class GenerateHashTreeUtil { LoggerUtil.info("报告ID" + runRequest.getReportId() + " 场景资源:" + item.getName() + ", 生成执行脚本JMX成功"); } catch (Exception ex) { - RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class); - remakeReportService.remake(runRequest); - ResultDTO dto = new ResultDTO(); - BeanUtils.copyBean(dto, runRequest); - CommonBeanFactory.getBean(ApiExecutionQueueService.class).queueNext(dto); + remakeException(runRequest); LoggerUtil.error("报告ID" + runRequest.getReportId() + " 场景资源:" + item.getName() + ", 生成执行脚本失败", ex); } ParameterConfig config = new ParameterConfig(); @@ -170,8 +166,20 @@ public class GenerateHashTreeUtil { return jmeterHashTree; } + public static void remakeException(JmeterRunRequestDTO runRequest) { + RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class); + remakeReportService.remake(runRequest); + ResultDTO dto = new ResultDTO(); + BeanUtils.copyBean(dto, runRequest); + CommonBeanFactory.getBean(ApiExecutionQueueService.class).queueNext(dto); + } + public static boolean isSetReport(RunModeConfigDTO config) { - return config != null && StringUtils.equals(config.getReportType(), RunModeConstants.SET_REPORT.toString()) && StringUtils.isNotEmpty(config.getReportName()); + return config != null && isSetReport(config.getReportType()) && StringUtils.isNotEmpty(config.getReportName()); + } + + public static boolean isSetReport(String reportType) { + return StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString()); } public static String getPlatformUrl(BaseSystemConfigDTO baseInfo, JmeterRunRequestDTO request, String queueDetailId) { @@ -189,4 +197,4 @@ public class GenerateHashTreeUtil { + "&queueId=" + queueDetailId; return platformUrl; } -} \ No newline at end of file +} diff --git a/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java b/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java index 75386f7c59..4f7075e03c 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/JMeterService.java @@ -6,7 +6,6 @@ import io.metersphere.api.exec.utils.GenerateHashTreeUtil; import io.metersphere.api.jmeter.utils.ServerConfig; import io.metersphere.api.jmeter.utils.SmoothWeighted; import io.metersphere.api.service.RemakeReportService; -import io.metersphere.base.domain.TestResource; import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.config.JmeterProperties; @@ -194,15 +193,6 @@ public class JMeterService { } } - @Deprecated - public void run(JmeterRunRequestDTO request, List resources) { - if (request.getPool().isPool()) { - this.runNode(request); - } else { - CommonBeanFactory.getBean(ExecThreadPoolExecutor.class).addTask(request); - } - } - public void addQueue(JmeterRunRequestDTO request) { this.runLocal(request); } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiExecutionQueueService.java b/backend/src/main/java/io/metersphere/api/service/ApiExecutionQueueService.java index 3e192b2695..43f4379f86 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiExecutionQueueService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiExecutionQueueService.java @@ -1,7 +1,9 @@ package io.metersphere.api.service; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import io.metersphere.api.dto.RunModeDataDTO; +import io.metersphere.api.dto.UiExecutionQueueParam; import io.metersphere.api.dto.automation.ScenarioStatus; import io.metersphere.api.exec.queue.DBTestQueue; import io.metersphere.api.exec.scenario.ApiScenarioSerialService; @@ -40,7 +42,7 @@ import java.util.stream.Collectors; @Service public class ApiExecutionQueueService { @Resource - private ApiExecutionQueueMapper queueMapper; + protected ApiExecutionQueueMapper queueMapper; @Resource private ApiExecutionQueueDetailMapper executionQueueDetailMapper; @Resource @@ -48,6 +50,8 @@ public class ApiExecutionQueueService { @Resource private ApiScenarioSerialService apiScenarioSerialService; @Resource + private UiScenarioSerialServiceProxy uiScenarioSerialServiceProxy; + @Resource private ApiScenarioReportService apiScenarioReportService; @Resource private ApiScenarioReportMapper apiScenarioReportMapper; @@ -60,7 +64,7 @@ public class ApiExecutionQueueService { @Resource private JMeterService jMeterService; @Resource - private ExtApiExecutionQueueMapper extApiExecutionQueueMapper; + protected ExtApiExecutionQueueMapper extApiExecutionQueueMapper; @Resource private ApiScenarioReportResultMapper apiScenarioReportResultMapper; @Lazy @@ -72,14 +76,7 @@ public class ApiExecutionQueueService { public DBTestQueue add(Object runObj, String poolId, String type, String reportId, String reportType, String runMode, RunModeConfigDTO config) { LoggerUtil.info("开始生成执行链"); - ApiExecutionQueue executionQueue = new ApiExecutionQueue(); - executionQueue.setId(UUID.randomUUID().toString()); - executionQueue.setCreateTime(System.currentTimeMillis()); - executionQueue.setPoolId(poolId); - executionQueue.setFailure(config.isOnSampleError()); - executionQueue.setReportId(reportId); - executionQueue.setReportType(StringUtils.isNotEmpty(reportType) ? reportType : RunModeConstants.INDEPENDENCE.toString()); - executionQueue.setRunMode(runMode); + ApiExecutionQueue executionQueue = getApiExecutionQueue(poolId, reportId, reportType, runMode, config); queueMapper.insert(executionQueue); DBTestQueue resQueue = new DBTestQueue(); BeanUtils.copyBean(resQueue, executionQueue); @@ -125,7 +122,13 @@ public class ApiExecutionQueueService { Map runMap = (Map) runObj; final int[] sort = {0}; runMap.forEach((k, v) -> { - ApiExecutionQueueDetail queue = detail(k, v.getTestId(), config.getMode(), sort[0], executionQueue.getId(), JSON.toJSONString(v.getPlanEnvMap())); + String envMap = JSON.toJSONString(v.getPlanEnvMap()); + if (StringUtils.startsWith(type, "UI_")) { + UiExecutionQueueParam param = new UiExecutionQueueParam(); + BeanUtils.copyBean(param, config); + envMap = JSONObject.toJSONString(param); + } + ApiExecutionQueueDetail queue = detail(k, v.getTestId(), config.getMode(), sort[0], executionQueue.getId(), envMap); queue.setSort(sort[0]); if (sort[0] == 0) { resQueue.setQueue(queue); @@ -146,7 +149,19 @@ public class ApiExecutionQueueService { return resQueue; } - private ApiExecutionQueueDetail detail(String reportId, String testId, String type, int sort, String queueId, String envMap) { + protected ApiExecutionQueue getApiExecutionQueue(String poolId, String reportId, String reportType, String runMode, RunModeConfigDTO config) { + ApiExecutionQueue executionQueue = new ApiExecutionQueue(); + executionQueue.setId(UUID.randomUUID().toString()); + executionQueue.setCreateTime(System.currentTimeMillis()); + executionQueue.setPoolId(poolId); + executionQueue.setFailure(config.isOnSampleError()); + executionQueue.setReportId(reportId); + executionQueue.setReportType(StringUtils.isNotEmpty(reportType) ? reportType : RunModeConstants.INDEPENDENCE.toString()); + executionQueue.setRunMode(runMode); + return executionQueue; + } + + protected ApiExecutionQueueDetail detail(String reportId, String testId, String type, int sort, String queueId, String envMap) { ApiExecutionQueueDetail queue = new ApiExecutionQueueDetail(); queue.setCreateTime(System.currentTimeMillis()); queue.setId(UUID.randomUUID().toString()); @@ -162,9 +177,7 @@ public class ApiExecutionQueueService { private boolean failure(DBTestQueue executionQueue, ResultDTO dto) { LoggerUtil.info("进入失败停止处理:" + executionQueue.getId()); boolean isError = false; - if (StringUtils.equalsAnyIgnoreCase(dto.getRunMode(), ApiRunMode.SCENARIO.name(), - ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), - ApiRunMode.SCHEDULE_SCENARIO.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name())) { + if (StringUtils.contains(dto.getRunMode(), ApiRunMode.SCENARIO.name())) { if (StringUtils.equals(dto.getReportType(), RunModeConstants.SET_REPORT.toString())) { ApiScenarioReportResultExample example = new ApiScenarioReportResultExample(); example.createCriteria().andReportIdEqualTo(dto.getReportId()).andStatusEqualTo(ExecuteResult.Error.name()); @@ -315,7 +328,11 @@ public class ApiExecutionQueueService { boolean isNext = redisTemplate.opsForValue().setIfAbsent(RunModeConstants.SERIAL.name() + "_" + executionQueue.getQueue().getReportId(), executionQueue.getQueue().getQueueId()); if (isNext) { redisTemplate.expire(RunModeConstants.SERIAL.name() + "_" + executionQueue.getQueue().getReportId(), 60, TimeUnit.MINUTES); - apiScenarioSerialService.serial(executionQueue, executionQueue.getQueue()); + if (StringUtils.startsWith(executionQueue.getRunMode(), "UI")) { + uiScenarioSerialServiceProxy.serial(executionQueue, executionQueue.getQueue()); + } else { + apiScenarioSerialService.serial(executionQueue, executionQueue.getQueue()); + } } } } else { diff --git a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportStructureService.java b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportStructureService.java index a13a5227be..6630d73b83 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportStructureService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportStructureService.java @@ -142,7 +142,7 @@ public class ApiScenarioReportStructureService { } public static StepTreeDTO dataFormatting(UiScenarioWithBLOBs uiScenario, String reportType) { - return dataFormatting(uiScenario.getId(), uiScenario.getName(), uiScenario.getScenarioDefinition(), reportType); + return dataFormatting(null, uiScenario.getName(), uiScenario.getScenarioDefinition(), reportType); } public static StepTreeDTO dataFormatting(String id, String name, String scenarioDefinition, String reportType) { diff --git a/backend/src/main/java/io/metersphere/api/service/RemakeReportService.java b/backend/src/main/java/io/metersphere/api/service/RemakeReportService.java index 6d2e6fe7f2..ee091f3fca 100644 --- a/backend/src/main/java/io/metersphere/api/service/RemakeReportService.java +++ b/backend/src/main/java/io/metersphere/api/service/RemakeReportService.java @@ -107,7 +107,10 @@ public class RemakeReportService { } apiScenarioReportMapper.updateByPrimaryKeySelective(report); } - } else { + } else if (StringUtils.equalsAny(request.getRunMode(), ApiRunMode.UI_SCENARIO_PLAN.name(), + request.getRunMode(), ApiRunMode.UI_SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.UI_JENKINS_SCENARIO_PLAN.name())) { + remarkUiScenarioPlan(request); + }else { ApiScenarioReportWithBLOBs report = apiScenarioReportMapper.selectByPrimaryKey(request.getReportId()); if (report != null) { report.setStatus(APITestStatus.Error.name()); @@ -135,6 +138,11 @@ public class RemakeReportService { } } + private void remarkUiScenarioPlan(JmeterRunRequestDTO request) { + // todo + } + + public void remakeScenario(String runMode, String scenarioId, ApiScenarioWithBLOBs scenarioWithBLOBs, ApiScenarioReportWithBLOBs report) { // 生成失败报告 if (StringUtils.equalsAny(runMode, ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name(), ApiRunMode.SCENARIO_PLAN.name())) { diff --git a/backend/src/main/java/io/metersphere/api/service/UiReportServiceProxy.java b/backend/src/main/java/io/metersphere/api/service/UiReportServiceProxy.java index fa132910cc..4786d892ab 100644 --- a/backend/src/main/java/io/metersphere/api/service/UiReportServiceProxy.java +++ b/backend/src/main/java/io/metersphere/api/service/UiReportServiceProxy.java @@ -1,7 +1,6 @@ package io.metersphere.api.service; import io.metersphere.commons.utils.CommonBeanFactory; -import io.metersphere.commons.utils.LogUtil; import io.metersphere.dto.RequestResult; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -26,15 +25,7 @@ public class UiReportServiceProxy { } private Object invoke(Function getDeclaredMethod, Object... args) { - Object uiAutomationService = CommonBeanFactory.getBean("uiReportService"); - try { - Class clazz = uiAutomationService.getClass(); - Method postProcessUiReport = getDeclaredMethod.apply(clazz); - return postProcessUiReport.invoke(uiAutomationService, args); - } catch (Exception e) { - LogUtil.error(e); - } - return null; + return CommonBeanFactory.invoke("uiReportService", getDeclaredMethod, args); } } diff --git a/backend/src/main/java/io/metersphere/api/service/UiScenarioSerialServiceProxy.java b/backend/src/main/java/io/metersphere/api/service/UiScenarioSerialServiceProxy.java new file mode 100644 index 0000000000..09cc508f21 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/service/UiScenarioSerialServiceProxy.java @@ -0,0 +1,31 @@ +package io.metersphere.api.service; + +import io.metersphere.base.domain.ApiExecutionQueue; +import io.metersphere.base.domain.ApiExecutionQueueDetail; +import io.metersphere.commons.utils.CommonBeanFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.lang.reflect.Method; +import java.util.function.Function; + +@Service +@Transactional(rollbackFor = Exception.class) +public class UiScenarioSerialServiceProxy { + + public Object serial(ApiExecutionQueue executionQueue, ApiExecutionQueueDetail queue) { + return invoke((clazz) -> { + try { + return clazz.getDeclaredMethod("serial", ApiExecutionQueue.class, ApiExecutionQueueDetail.class); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + return null; + } + }, executionQueue, queue); + } + + private Object invoke(Function getDeclaredMethod, Object... args) { + return CommonBeanFactory.invoke("uiScenarioSerialService", getDeclaredMethod, args); + } + +} diff --git a/backend/src/main/java/io/metersphere/commons/utils/CommonBeanFactory.java b/backend/src/main/java/io/metersphere/commons/utils/CommonBeanFactory.java index 1653b98429..03a2f4bd77 100644 --- a/backend/src/main/java/io/metersphere/commons/utils/CommonBeanFactory.java +++ b/backend/src/main/java/io/metersphere/commons/utils/CommonBeanFactory.java @@ -5,7 +5,9 @@ import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import java.lang.reflect.Method; import java.util.Map; +import java.util.function.Function; public class CommonBeanFactory implements ApplicationContextAware { private static ApplicationContext context; @@ -36,5 +38,16 @@ public class CommonBeanFactory implements ApplicationContextAware { public static Map getBeansOfType(Class className) { return context.getBeansOfType(className); } + + public static Object invoke(String beanName, Function methodFunction, Object... args) { + Object bean = getBean(beanName); + try { + Class clazz = bean.getClass(); + return methodFunction.apply(clazz).invoke(bean, args); + } catch (Exception e) { + LogUtil.error(e); + } + return null; + } }