fix(测试跟踪): 数据太多时,测试计划报告列表内存溢出

--bug=1020253 --user=陈建星 【测试跟踪】访问报告页面,服务会挂 https://www.tapd.cn/55049933/s/1305503
This commit is contained in:
chenjianxing 2022-11-25 15:24:55 +08:00 committed by jianxing
parent f4ccfa60d4
commit c5f3767fc9
5 changed files with 137 additions and 120 deletions

View File

@ -0,0 +1,11 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.base.domain.TestPlanReportContentWithBLOBs;
import org.apache.ibatis.annotations.Param;
public interface ExtTestPlanReportContentMapper {
boolean isDynamicallyGenerateReport(@Param("reportId") String reportId);
TestPlanReportContentWithBLOBs selectForPassRate(@Param("reportId") String reportId);
}

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="io.metersphere.base.mapper.ext.ExtTestPlanReportContentMapper">
<select id="isDynamicallyGenerateReport" resultType="java.lang.Boolean">
select count(*) > 0
from test_plan_report_content
where test_plan_report_id = #{reportId}
and (
plan_api_case_report_struct is not null or plan_api_case_report_struct != ''
or plan_scenario_report_struct is not null or plan_scenario_report_struct != ''
or plan_ui_scenario_report_struct is not null or plan_ui_scenario_report_struct != ''
or plan_load_case_report_struct is not null or plan_load_case_report_struct != ''
)
</select>
<select id="selectForPassRate" resultType="io.metersphere.base.domain.TestPlanReportContentWithBLOBs">
select id,
test_plan_report_id,
plan_scenario_report_struct,
plan_api_case_report_struct,
plan_load_case_report_struct,
plan_ui_scenario_report_struct
from test_plan_report_content
where test_plan_report_id = #{reportId}
</select>
</mapper>

View File

@ -4,6 +4,7 @@ package io.metersphere.plan.service;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*; import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtTestPlanMapper; import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanReportContentMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanReportMapper; import io.metersphere.base.mapper.ext.ExtTestPlanReportMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper; import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
import io.metersphere.commons.constants.*; import io.metersphere.commons.constants.*;
@ -73,6 +74,8 @@ public class TestPlanReportService {
@Resource @Resource
TestPlanReportContentMapper testPlanReportContentMapper; TestPlanReportContentMapper testPlanReportContentMapper;
@Resource @Resource
ExtTestPlanReportContentMapper extTestPlanReportContentMapper;
@Resource
private TestPlanPrincipalMapper testPlanPrincipalMapper; private TestPlanPrincipalMapper testPlanPrincipalMapper;
@Resource @Resource
ExtTestPlanTestCaseMapper extTestPlanTestCaseMapper; ExtTestPlanTestCaseMapper extTestPlanTestCaseMapper;
@ -136,14 +139,8 @@ public class TestPlanReportService {
for (TestPlanReportDTO testPlanReportDTO : list) { for (TestPlanReportDTO testPlanReportDTO : list) {
// 如果数据库查询成功率字段为空或 0 则重新计算一次 // 如果数据库查询成功率字段为空或 0 则重新计算一次
if (testPlanReportDTO.getPassRate() == null || testPlanReportDTO.getPassRate() == 0) { if (testPlanReportDTO.getPassRate() == null || testPlanReportDTO.getPassRate() == 0) {
TestPlanReportContentExample example = new TestPlanReportContentExample(); if (this.isDynamicallyGenerateReports(testPlanReportDTO.getId())) {
example.createCriteria().andTestPlanReportIdEqualTo(testPlanReportDTO.getId()); TestPlanReportContentWithBLOBs testPlanReportContent = extTestPlanReportContentMapper.selectForPassRate(testPlanReportDTO.getId());
List<TestPlanReportContentWithBLOBs> testPlanReportContents = testPlanReportContentMapper.selectByExampleWithBLOBs(example);
if (CollectionUtils.isNotEmpty(testPlanReportContents)) {
TestPlanReportContentWithBLOBs testPlanReportContent = testPlanReportContents.get(0);
if (testPlanReportContent != null) {
if (this.isDynamicallyGenerateReports(testPlanReportContent)) {
String planId = testPlanReportDTO.getTestPlanId(); String planId = testPlanReportDTO.getTestPlanId();
TestPlanSimpleReportDTO report = new TestPlanSimpleReportDTO(); TestPlanSimpleReportDTO report = new TestPlanSimpleReportDTO();
Map<String, TestCaseReportStatusResultDTO> statusResultMap = new HashMap<>(); Map<String, TestCaseReportStatusResultDTO> statusResultMap = new HashMap<>();
@ -224,8 +221,6 @@ public class TestPlanReportService {
} }
} }
} }
}
}
public TestPlanScheduleReportInfoDTO genTestPlanReportBySchedule(String planReportId, String planId, String userId, String triggerMode, RunModeConfigDTO runModeConfigDTO) { public TestPlanScheduleReportInfoDTO genTestPlanReportBySchedule(String planReportId, String planId, String userId, String triggerMode, RunModeConfigDTO runModeConfigDTO) {
TestPlanReport testPlanReport = this.getTestPlanReport(planReportId); TestPlanReport testPlanReport = this.getTestPlanReport(planReportId);
@ -475,7 +470,8 @@ public class TestPlanReportService {
private void updatePassRateAndApiBaseInfoFromReportContent(String status, TestPlanSimpleReportDTO reportDTO, TestPlanReportContentWithBLOBs reportContent, boolean apiBaseInfoChanged) { private void updatePassRateAndApiBaseInfoFromReportContent(String status, TestPlanSimpleReportDTO reportDTO, TestPlanReportContentWithBLOBs reportContent, boolean apiBaseInfoChanged) {
// 如果报告已结束则更新测试计划报告通过率字段 passRate // 如果报告已结束则更新测试计划报告通过率字段 passRate
if (!StringUtils.equalsIgnoreCase(status, "running") && (Double.compare(reportContent.getPassRate(), reportDTO.getPassRate()) != 0 || apiBaseInfoChanged)) { if (!StringUtils.equalsIgnoreCase(status, APITestStatus.Running.name())
&& (Double.compare(reportContent.getPassRate(), reportDTO.getPassRate()) != 0 || apiBaseInfoChanged)) {
TestPlanReportContentExample contentExample = new TestPlanReportContentExample(); TestPlanReportContentExample contentExample = new TestPlanReportContentExample();
contentExample.createCriteria().andTestPlanReportIdEqualTo(reportContent.getTestPlanReportId()); contentExample.createCriteria().andTestPlanReportIdEqualTo(reportContent.getTestPlanReportId());
TestPlanReportContentWithBLOBs content = new TestPlanReportContentWithBLOBs(); TestPlanReportContentWithBLOBs content = new TestPlanReportContentWithBLOBs();
@ -1084,6 +1080,10 @@ public class TestPlanReportService {
(StringUtils.isNotEmpty(testPlanReportContent.getPlanApiCaseReportStruct()) || StringUtils.isNotEmpty(testPlanReportContent.getPlanScenarioReportStruct()) || StringUtils.isNotEmpty(testPlanReportContent.getPlanLoadCaseReportStruct()) || StringUtils.isNotEmpty(testPlanReportContent.getPlanUiScenarioReportStruct())); (StringUtils.isNotEmpty(testPlanReportContent.getPlanApiCaseReportStruct()) || StringUtils.isNotEmpty(testPlanReportContent.getPlanScenarioReportStruct()) || StringUtils.isNotEmpty(testPlanReportContent.getPlanLoadCaseReportStruct()) || StringUtils.isNotEmpty(testPlanReportContent.getPlanUiScenarioReportStruct()));
} }
private boolean isDynamicallyGenerateReports(String reportId) {
return extTestPlanReportContentMapper.isDynamicallyGenerateReport(reportId);
}
private TestPlanReportContentWithBLOBs dynamicallyGenerateReports(TestPlanReportContentWithBLOBs testPlanReportContent) { private TestPlanReportContentWithBLOBs dynamicallyGenerateReports(TestPlanReportContentWithBLOBs testPlanReportContent) {
TestPlanReport report = testPlanReportMapper.selectByPrimaryKey(testPlanReportContent.getTestPlanReportId()); TestPlanReport report = testPlanReportMapper.selectByPrimaryKey(testPlanReportContent.getTestPlanReportId());
testPlanReportContent = this.updateReport(report, testPlanReportContent); testPlanReportContent = this.updateReport(report, testPlanReportContent);

View File

@ -12,30 +12,10 @@
import TestPlanReportList from './components/TestPlanReportList'; import TestPlanReportList from './components/TestPlanReportList';
import MsContainer from "metersphere-frontend/src/components/MsContainer"; import MsContainer from "metersphere-frontend/src/components/MsContainer";
import MsMainContainer from "metersphere-frontend/src/components/MsMainContainer"; import MsMainContainer from "metersphere-frontend/src/components/MsMainContainer";
import {TEST_PLAN_REPORT_CONFIGS} from "metersphere-frontend/src/components/search/search-components";
export default { export default {
name: "TestPlanReport", name: "TestPlanReport",
components: {MsMainContainer, MsContainer, TestPlanReportList}, components: {MsMainContainer, MsContainer, TestPlanReportList},
data() {
return {}
},
activated() {
this.refreshTestPlanList();
},
mounted() {
this.refreshTestPlanList();
},
watch: {
'$route'(to, from) {
}
},
methods: {
refreshTestPlanList() {
this.$refs.testPlanReportList.condition = {components: TEST_PLAN_REPORT_CONFIGS};
this.$refs.testPlanReportList.initTableData();
}
}
} }
</script> </script>

View File

@ -234,9 +234,10 @@ export default {
} }
}, },
activated() { activated() {
this.init();
}, },
created() { methods: {
init() {
this.projectId = this.$route.params.projectId; this.projectId = this.$route.params.projectId;
this.batchButtons = this.publicButtons; this.batchButtons = this.publicButtons;
this.operators = this.simpleOperators; this.operators = this.simpleOperators;
@ -255,7 +256,6 @@ export default {
}); });
} }
}, },
methods: {
initTableData() { initTableData() {
initCondition(this.condition, this.condition.selectAll); initCondition(this.condition, this.condition.selectAll);
this.condition.orders = getLastTableSortField(this.tableHeaderKey); this.condition.orders = getLastTableSortField(this.tableHeaderKey);