fix(性能测试): 修复报告页面下载zip都是最新文件的问题

--bug=1013315 --user=刘瑞斌 【性能测试】github#13720,性能测试一个任务多个报告,历史的报告下载的也是最新的 jmx 执行文件 https://www.tapd.cn/55049933/s/1161694

Closes #13720
This commit is contained in:
CaptainB 2022-05-21 15:12:50 +08:00 committed by f2c-ci-robot[bot]
parent 5242670548
commit 87a45eebd8
12 changed files with 635 additions and 17 deletions

View File

@ -0,0 +1,15 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
@Data
public class LoadTestReportFile implements Serializable {
private String reportId;
private String fileId;
private Integer sort;
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,400 @@
package io.metersphere.base.domain;
import java.util.ArrayList;
import java.util.List;
public class LoadTestReportFileExample {
protected String orderByClause;
protected boolean distinct;
protected List<Criteria> oredCriteria;
public LoadTestReportFileExample() {
oredCriteria = new ArrayList<Criteria>();
}
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
public String getOrderByClause() {
return orderByClause;
}
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
public boolean isDistinct() {
return distinct;
}
public List<Criteria> getOredCriteria() {
return oredCriteria;
}
public void or(Criteria criteria) {
oredCriteria.add(criteria);
}
public Criteria or() {
Criteria criteria = createCriteriaInternal();
oredCriteria.add(criteria);
return criteria;
}
public Criteria createCriteria() {
Criteria criteria = createCriteriaInternal();
if (oredCriteria.size() == 0) {
oredCriteria.add(criteria);
}
return criteria;
}
protected Criteria createCriteriaInternal() {
Criteria criteria = new Criteria();
return criteria;
}
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
}
protected abstract static class GeneratedCriteria {
protected List<Criterion> criteria;
protected GeneratedCriteria() {
super();
criteria = new ArrayList<Criterion>();
}
public boolean isValid() {
return criteria.size() > 0;
}
public List<Criterion> getAllCriteria() {
return criteria;
}
public List<Criterion> getCriteria() {
return criteria;
}
protected void addCriterion(String condition) {
if (condition == null) {
throw new RuntimeException("Value for condition cannot be null");
}
criteria.add(new Criterion(condition));
}
protected void addCriterion(String condition, Object value, String property) {
if (value == null) {
throw new RuntimeException("Value for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value));
}
protected void addCriterion(String condition, Object value1, Object value2, String property) {
if (value1 == null || value2 == null) {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andReportIdIsNull() {
addCriterion("report_id is null");
return (Criteria) this;
}
public Criteria andReportIdIsNotNull() {
addCriterion("report_id is not null");
return (Criteria) this;
}
public Criteria andReportIdEqualTo(String value) {
addCriterion("report_id =", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdNotEqualTo(String value) {
addCriterion("report_id <>", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdGreaterThan(String value) {
addCriterion("report_id >", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdGreaterThanOrEqualTo(String value) {
addCriterion("report_id >=", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdLessThan(String value) {
addCriterion("report_id <", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdLessThanOrEqualTo(String value) {
addCriterion("report_id <=", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdLike(String value) {
addCriterion("report_id like", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdNotLike(String value) {
addCriterion("report_id not like", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdIn(List<String> values) {
addCriterion("report_id in", values, "reportId");
return (Criteria) this;
}
public Criteria andReportIdNotIn(List<String> values) {
addCriterion("report_id not in", values, "reportId");
return (Criteria) this;
}
public Criteria andReportIdBetween(String value1, String value2) {
addCriterion("report_id between", value1, value2, "reportId");
return (Criteria) this;
}
public Criteria andReportIdNotBetween(String value1, String value2) {
addCriterion("report_id not between", value1, value2, "reportId");
return (Criteria) this;
}
public Criteria andFileIdIsNull() {
addCriterion("file_id is null");
return (Criteria) this;
}
public Criteria andFileIdIsNotNull() {
addCriterion("file_id is not null");
return (Criteria) this;
}
public Criteria andFileIdEqualTo(String value) {
addCriterion("file_id =", value, "fileId");
return (Criteria) this;
}
public Criteria andFileIdNotEqualTo(String value) {
addCriterion("file_id <>", value, "fileId");
return (Criteria) this;
}
public Criteria andFileIdGreaterThan(String value) {
addCriterion("file_id >", value, "fileId");
return (Criteria) this;
}
public Criteria andFileIdGreaterThanOrEqualTo(String value) {
addCriterion("file_id >=", value, "fileId");
return (Criteria) this;
}
public Criteria andFileIdLessThan(String value) {
addCriterion("file_id <", value, "fileId");
return (Criteria) this;
}
public Criteria andFileIdLessThanOrEqualTo(String value) {
addCriterion("file_id <=", value, "fileId");
return (Criteria) this;
}
public Criteria andFileIdLike(String value) {
addCriterion("file_id like", value, "fileId");
return (Criteria) this;
}
public Criteria andFileIdNotLike(String value) {
addCriterion("file_id not like", value, "fileId");
return (Criteria) this;
}
public Criteria andFileIdIn(List<String> values) {
addCriterion("file_id in", values, "fileId");
return (Criteria) this;
}
public Criteria andFileIdNotIn(List<String> values) {
addCriterion("file_id not in", values, "fileId");
return (Criteria) this;
}
public Criteria andFileIdBetween(String value1, String value2) {
addCriterion("file_id between", value1, value2, "fileId");
return (Criteria) this;
}
public Criteria andFileIdNotBetween(String value1, String value2) {
addCriterion("file_id not between", value1, value2, "fileId");
return (Criteria) this;
}
public Criteria andSortIsNull() {
addCriterion("sort is null");
return (Criteria) this;
}
public Criteria andSortIsNotNull() {
addCriterion("sort is not null");
return (Criteria) this;
}
public Criteria andSortEqualTo(Integer value) {
addCriterion("sort =", value, "sort");
return (Criteria) this;
}
public Criteria andSortNotEqualTo(Integer value) {
addCriterion("sort <>", value, "sort");
return (Criteria) this;
}
public Criteria andSortGreaterThan(Integer value) {
addCriterion("sort >", value, "sort");
return (Criteria) this;
}
public Criteria andSortGreaterThanOrEqualTo(Integer value) {
addCriterion("sort >=", value, "sort");
return (Criteria) this;
}
public Criteria andSortLessThan(Integer value) {
addCriterion("sort <", value, "sort");
return (Criteria) this;
}
public Criteria andSortLessThanOrEqualTo(Integer value) {
addCriterion("sort <=", value, "sort");
return (Criteria) this;
}
public Criteria andSortIn(List<Integer> values) {
addCriterion("sort in", values, "sort");
return (Criteria) this;
}
public Criteria andSortNotIn(List<Integer> values) {
addCriterion("sort not in", values, "sort");
return (Criteria) this;
}
public Criteria andSortBetween(Integer value1, Integer value2) {
addCriterion("sort between", value1, value2, "sort");
return (Criteria) this;
}
public Criteria andSortNotBetween(Integer value1, Integer value2) {
addCriterion("sort not between", value1, value2, "sort");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {
protected Criteria() {
super();
}
}
public static class Criterion {
private String condition;
private Object value;
private Object secondValue;
private boolean noValue;
private boolean singleValue;
private boolean betweenValue;
private boolean listValue;
private String typeHandler;
public String getCondition() {
return condition;
}
public Object getValue() {
return value;
}
public Object getSecondValue() {
return secondValue;
}
public boolean isNoValue() {
return noValue;
}
public boolean isSingleValue() {
return singleValue;
}
public boolean isBetweenValue() {
return betweenValue;
}
public boolean isListValue() {
return listValue;
}
public String getTypeHandler() {
return typeHandler;
}
protected Criterion(String condition) {
super();
this.condition = condition;
this.typeHandler = null;
this.noValue = true;
}
protected Criterion(String condition, Object value, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.typeHandler = typeHandler;
if (value instanceof List<?>) {
this.listValue = true;
} else {
this.singleValue = true;
}
}
protected Criterion(String condition, Object value) {
this(condition, value, null);
}
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.secondValue = secondValue;
this.typeHandler = typeHandler;
this.betweenValue = true;
}
protected Criterion(String condition, Object value, Object secondValue) {
this(condition, value, secondValue, null);
}
}
}

View File

@ -0,0 +1,22 @@
package io.metersphere.base.mapper;
import io.metersphere.base.domain.LoadTestReportFile;
import io.metersphere.base.domain.LoadTestReportFileExample;
import java.util.List;
import org.apache.ibatis.annotations.Param;
public interface LoadTestReportFileMapper {
long countByExample(LoadTestReportFileExample example);
int deleteByExample(LoadTestReportFileExample example);
int insert(LoadTestReportFile record);
int insertSelective(LoadTestReportFile record);
List<LoadTestReportFile> selectByExample(LoadTestReportFileExample example);
int updateByExampleSelective(@Param("record") LoadTestReportFile record, @Param("example") LoadTestReportFileExample example);
int updateByExample(@Param("record") LoadTestReportFile record, @Param("example") LoadTestReportFileExample example);
}

View File

@ -0,0 +1,153 @@
<?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.LoadTestReportFileMapper">
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.LoadTestReportFile">
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
<result column="file_id" jdbcType="VARCHAR" property="fileId" />
<result column="sort" jdbcType="INTEGER" property="sort" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Update_By_Example_Where_Clause">
<where>
<foreach collection="example.oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Base_Column_List">
report_id, file_id, sort
</sql>
<select id="selectByExample" parameterType="io.metersphere.base.domain.LoadTestReportFileExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from load_test_report_file
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.LoadTestReportFileExample">
delete from load_test_report_file
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.base.domain.LoadTestReportFile">
insert into load_test_report_file (report_id, file_id, sort
)
values (#{reportId,jdbcType=VARCHAR}, #{fileId,jdbcType=VARCHAR}, #{sort,jdbcType=INTEGER}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.LoadTestReportFile">
insert into load_test_report_file
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="reportId != null">
report_id,
</if>
<if test="fileId != null">
file_id,
</if>
<if test="sort != null">
sort,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="reportId != null">
#{reportId,jdbcType=VARCHAR},
</if>
<if test="fileId != null">
#{fileId,jdbcType=VARCHAR},
</if>
<if test="sort != null">
#{sort,jdbcType=INTEGER},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.base.domain.LoadTestReportFileExample" resultType="java.lang.Long">
select count(*) from load_test_report_file
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
update load_test_report_file
<set>
<if test="record.reportId != null">
report_id = #{record.reportId,jdbcType=VARCHAR},
</if>
<if test="record.fileId != null">
file_id = #{record.fileId,jdbcType=VARCHAR},
</if>
<if test="record.sort != null">
sort = #{record.sort,jdbcType=INTEGER},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update load_test_report_file
set report_id = #{record.reportId,jdbcType=VARCHAR},
file_id = #{record.fileId,jdbcType=VARCHAR},
sort = #{record.sort,jdbcType=INTEGER}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
</mapper>

View File

@ -1,5 +1,6 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.base.domain.FileMetadata;
import io.metersphere.base.domain.LoadTestReport;
import io.metersphere.base.domain.LoadTestReportWithBLOBs;
import io.metersphere.dto.DashboardTestDTO;
@ -27,4 +28,6 @@ public interface ExtLoadTestReportMapper {
List<PlanReportCaseDTO> selectForPlanReport(@Param("ids") List<String> reportIds);
int updateReportVumStatus(String reportId,String reportKey ,String nextStatus, String preStatus);
List<FileMetadata> getFileMetadataById(@Param("reportId") String reportId);
}

View File

@ -194,4 +194,11 @@
and report_value = #{preStatus,jdbcType=VARCHAR}
</update>
<select id="getFileMetadataById" resultType="io.metersphere.base.domain.FileMetadata">
SELECT file_metadata.*
FROM load_test_report_file
JOIN file_metadata ON file_id = file_metadata.id
WHERE report_id = #{reportId}
ORDER BY sort
</select>
</mapper>

View File

@ -3,6 +3,7 @@ package io.metersphere.performance.controller;
import io.metersphere.commons.utils.WeakConcurrentHashMap;
import io.metersphere.controller.handler.annotation.NoResultHolder;
import io.metersphere.performance.dto.ZipDTO;
import io.metersphere.performance.service.JmeterFileService;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
@ -44,16 +45,15 @@ public class JmeterFileController {
}
@GetMapping("download")
public ResponseEntity<byte[]> downloadJmeterFiles(@RequestParam("testId") String testId,
@RequestParam("ratio") String ratio,
public ResponseEntity<byte[]> downloadJmeterFiles(@RequestParam("ratio") String ratio,
@RequestParam("reportId") String reportId,
@RequestParam("resourceIndex") int resourceIndex) {
double[] ratios = Arrays.stream(ratio.split(",")).mapToDouble(Double::parseDouble).toArray();
byte[] bytes = jmeterFileService.downloadZip(reportId, ratios, resourceIndex);
ZipDTO zipDTO = jmeterFileService.downloadZip(reportId, ratios, resourceIndex);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/octet-stream"))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + testId + ".zip\"")
.body(bytes);
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + zipDTO.getTestId() + ".zip\"")
.body(zipDTO.getContent());
}
}

View File

@ -0,0 +1,11 @@
package io.metersphere.performance.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class ZipDTO {
private String testId;
private byte[] content;
}

View File

@ -16,7 +16,7 @@ import io.metersphere.i18n.Translator;
import io.metersphere.performance.engine.docker.DockerTestEngine;
import io.metersphere.performance.parse.EngineSourceParser;
import io.metersphere.performance.parse.EngineSourceParserFactory;
import io.metersphere.performance.service.PerformanceTestService;
import io.metersphere.performance.service.PerformanceReportService;
import io.metersphere.service.FileService;
import io.metersphere.service.KubernetesTestEngine;
import io.metersphere.service.TestResourcePoolService;
@ -40,7 +40,7 @@ import java.util.stream.Collectors;
@Transactional(rollbackFor = Exception.class)
public class EngineFactory {
private static FileService fileService;
private static PerformanceTestService performanceTestService;
private static PerformanceReportService performanceReportService;
private static TestResourcePoolService testResourcePoolService;
public static Class<? extends KubernetesTestEngine> getKubernetesTestEngineClass() {
@ -94,10 +94,10 @@ public class EngineFactory {
return null;
}
public static EngineContext createContext(LoadTestReportWithBLOBs loadTestReport, double[] ratios, String reportId, int resourceIndex) {
final List<FileMetadata> fileMetadataList = performanceTestService.getFileMetadataByTestId(loadTestReport.getTestId());
if (org.springframework.util.CollectionUtils.isEmpty(fileMetadataList)) {
MSException.throwException(Translator.get("run_load_test_file_not_found") + loadTestReport.getTestId());
public static EngineContext createContext(LoadTestReportWithBLOBs loadTestReport, double[] ratios, int resourceIndex) {
final List<FileMetadata> fileMetadataList = performanceReportService.getFileMetadataByReportId(loadTestReport.getId());
if (CollectionUtils.isEmpty(fileMetadataList)) {
MSException.throwException(Translator.get("run_load_test_file_not_found") + loadTestReport.getId());
}
// 报告页面点击下载执行zip
boolean isLocal = false;
@ -116,7 +116,7 @@ public class EngineFactory {
engineContext.setNamespace(loadTestReport.getProjectId());
engineContext.setFileType(FileType.JMX.name());
engineContext.setResourcePoolId(loadTestReport.getTestResourcePoolId());
engineContext.setReportId(reportId);
engineContext.setReportId(loadTestReport.getId());
engineContext.setResourceIndex(resourceIndex);
engineContext.setRatios(ratios);
@ -379,7 +379,7 @@ public class EngineFactory {
}
@Resource
public void setPerformanceTestService(PerformanceTestService performanceTestService) {
EngineFactory.performanceTestService = performanceTestService;
public void setPerformanceReportService(PerformanceReportService performanceReportService) {
EngineFactory.performanceReportService = performanceReportService;
}
}

View File

@ -6,6 +6,7 @@ import io.metersphere.base.mapper.LoadTestReportMapper;
import io.metersphere.base.mapper.ext.ExtLoadTestReportMapper;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.performance.dto.ZipDTO;
import io.metersphere.performance.engine.EngineContext;
import io.metersphere.performance.engine.EngineFactory;
import org.springframework.stereotype.Service;
@ -28,7 +29,7 @@ public class JmeterFileService {
@Resource
private LoadTestReportMapper loadTestReportMapper;
public byte[] downloadZip(String reportId, double[] ratios, int resourceIndex) {
public ZipDTO downloadZip(String reportId, double[] ratios, int resourceIndex) {
try {
LoadTestReportWithBLOBs loadTestReport = loadTestReportMapper.selectByPrimaryKey(reportId);
int wait = 0;
@ -43,8 +44,9 @@ public class JmeterFileService {
if (loadTestReport == null) {
MSException.throwException("测试报告不存在或还没产生");
}
EngineContext context = EngineFactory.createContext(loadTestReport, ratios, reportId, resourceIndex);
return zipFilesToByteArray(context);
EngineContext context = EngineFactory.createContext(loadTestReport, ratios, resourceIndex);
byte[] bytes = zipFilesToByteArray(context);
return new ZipDTO(loadTestReport.getTestId(), bytes);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(e);

View File

@ -537,4 +537,8 @@ public class PerformanceReportService {
request.setIds(ids);
deleteReportBatch(request);
}
public List<FileMetadata> getFileMetadataByReportId(String reportId) {
return extLoadTestReportMapper.getFileMetadataById(reportId);
}
}

View File

@ -0,0 +1 @@
-- 初始化 sql