fix(测试跟踪): 测试跟踪重启时清理不再运行的执行队列

测试跟踪重启时清理不再运行的执行队列
This commit is contained in:
song-tianyang 2023-05-04 18:16:50 +08:00 committed by fit2-zhao
parent 3c9e39412c
commit 459e53cdf9
6 changed files with 80 additions and 13 deletions

View File

@ -2,9 +2,10 @@ package io.metersphere.base.mapper;
import io.metersphere.base.domain.TestPlanExecutionQueue; import io.metersphere.base.domain.TestPlanExecutionQueue;
import io.metersphere.base.domain.TestPlanExecutionQueueExample; import io.metersphere.base.domain.TestPlanExecutionQueueExample;
import java.util.List;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface TestPlanExecutionQueueMapper { public interface TestPlanExecutionQueueMapper {
long countByExample(TestPlanExecutionQueueExample example); long countByExample(TestPlanExecutionQueueExample example);
@ -27,4 +28,5 @@ public interface TestPlanExecutionQueueMapper {
int updateByPrimaryKeySelective(TestPlanExecutionQueue record); int updateByPrimaryKeySelective(TestPlanExecutionQueue record);
int updateByPrimaryKey(TestPlanExecutionQueue record); int updateByPrimaryKey(TestPlanExecutionQueue record);
} }

View File

@ -0,0 +1,8 @@
package io.metersphere.base.mapper.ext;
import java.util.List;
public interface ExtApiExecutionQueueMapper {
List<String> selectIdByReportIdIsNull();
}

View File

@ -0,0 +1,10 @@
<?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.ExtApiExecutionQueueMapper">
<select id="selectIdByReportIdIsNull" resultType="java.lang.String">
SELECT id
FROM api_execution_queue
WHERE report_id IS NOT NULL
</select>
</mapper>

View File

@ -2,7 +2,6 @@ package io.metersphere.plan.service;
import io.metersphere.base.domain.TestPlanWithBLOBs; import io.metersphere.base.domain.TestPlanWithBLOBs;
import io.metersphere.base.mapper.TestPlanMapper; import io.metersphere.base.mapper.TestPlanMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
import io.metersphere.commons.constants.TestPlanReportStatus; import io.metersphere.commons.constants.TestPlanReportStatus;
import io.metersphere.commons.utils.JSON; import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
@ -10,12 +9,10 @@ import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.*; import io.metersphere.dto.*;
import io.metersphere.plan.dto.ExecutionWay; import io.metersphere.plan.dto.ExecutionWay;
import io.metersphere.plan.request.api.TestPlanRunRequest; import io.metersphere.plan.request.api.TestPlanRunRequest;
import io.metersphere.plan.service.remote.api.PlanApiAutomationService;
import io.metersphere.plan.service.remote.api.PlanTestPlanApiCaseService; import io.metersphere.plan.service.remote.api.PlanTestPlanApiCaseService;
import io.metersphere.plan.service.remote.api.PlanTestPlanScenarioCaseService; import io.metersphere.plan.service.remote.api.PlanTestPlanScenarioCaseService;
import io.metersphere.plan.service.remote.performance.PerfExecService; import io.metersphere.plan.service.remote.performance.PerfExecService;
import io.metersphere.plan.service.remote.ui.PlanTestPlanUiScenarioCaseService; import io.metersphere.plan.service.remote.ui.PlanTestPlanUiScenarioCaseService;
import io.metersphere.plan.service.remote.ui.PlanUiAutomationService;
import io.metersphere.plan.utils.TestPlanRequestUtil; import io.metersphere.plan.utils.TestPlanRequestUtil;
import io.metersphere.utils.LoggerUtil; import io.metersphere.utils.LoggerUtil;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -45,15 +42,9 @@ public class TestPlanExecuteService {
private PerfExecService perfExecService; private PerfExecService perfExecService;
@Resource @Resource
private PlanTestPlanUiScenarioCaseService planTestPlanUiScenarioCaseService; private PlanTestPlanUiScenarioCaseService planTestPlanUiScenarioCaseService;
@Resource
private PlanApiAutomationService planApiAutomationService;
@Resource
private PlanUiAutomationService planUiAutomationService;
@Resource @Resource
private TestPlanMapper testPlanMapper; private TestPlanMapper testPlanMapper;
@Resource
private ExtTestPlanMapper extTestPlanMapper;
/** /**
* 执行测试计划流程是会调用其它服务的执行方法并通过kafka传递信息给test-track服务来判断测试计划是否执行结束 * 执行测试计划流程是会调用其它服务的执行方法并通过kafka传递信息给test-track服务来判断测试计划是否执行结束

View File

@ -124,6 +124,12 @@ public class TestPlanReportService {
@Lazy @Lazy
@Resource @Resource
private IssuesService issuesService; private IssuesService issuesService;
@Resource
private ApiExecutionQueueMapper apiExecutionQueueMapper;
@Resource
private ApiExecutionQueueDetailMapper apiExecutionQueueDetailMapper;
@Resource
private ExtApiExecutionQueueMapper extApiExecutionQueueMapper;
private final String GROUP = "GROUP"; private final String GROUP = "GROUP";
@ -872,7 +878,6 @@ public class TestPlanReportService {
TestPlanReportContentExample contentExample = new TestPlanReportContentExample(); TestPlanReportContentExample contentExample = new TestPlanReportContentExample();
contentExample.createCriteria().andTestPlanReportIdIn(testPlanReportIdList); contentExample.createCriteria().andTestPlanReportIdIn(testPlanReportIdList);
testPlanReportContentMapper.deleteByExample(contentExample); testPlanReportContentMapper.deleteByExample(contentExample);
// todo 删除场景接口的报告
BatchProcessingUtil.batchDeleteApiReport(testPlanReportIdList, this::deleteApiCaseReportByTestPlanExecute, this::deleteScenarioReportByTestPlanExecute, this::deleteUiReportByTestPlanExecute); BatchProcessingUtil.batchDeleteApiReport(testPlanReportIdList, this::deleteApiCaseReportByTestPlanExecute, this::deleteScenarioReportByTestPlanExecute, this::deleteUiReportByTestPlanExecute);
} }
} }
@ -1687,6 +1692,39 @@ public class TestPlanReportService {
LogUtil.info("开始处理服务重启导致执行未完成的报告状态"); LogUtil.info("开始处理服务重启导致执行未完成的报告状态");
extTestPlanReportMapper.updateAllStatus(); extTestPlanReportMapper.updateAllStatus();
LogUtil.info("处理服务重启导致执行未完成的报告状态完成"); LogUtil.info("处理服务重启导致执行未完成的报告状态完成");
LogUtil.info("开始清除测试计划相关的执行队列");
this.deleteAllQueue();
LogUtil.info("清除测试计划相关的执行队列完成");
}
public void deleteAllQueue() {
LogUtil.info("开始清除测试计划的资源执行队列");
//删除测试计划资源执行队列
List<String> queueDeleteIdList = extApiExecutionQueueMapper.selectIdByReportIdIsNull();
if (CollectionUtils.isNotEmpty(queueDeleteIdList)) {
BatchProcessingUtil.consumerByStringList(queueDeleteIdList, this::deleteApiExecutionQueueDetail);
BatchProcessingUtil.consumerByStringList(queueDeleteIdList, this::deleteApiExecutionQueue);
}
LogUtil.info("开始清除测试计划的批量串行执行队列");
//删除测试计划串行队列
TestPlanExecutionQueueExample example = new TestPlanExecutionQueueExample();
testPlanExecutionQueueMapper.deleteByExample(example);
}
public void deleteApiExecutionQueue(List<String> queueIdList) {
if (CollectionUtils.isNotEmpty(queueIdList)) {
ApiExecutionQueueExample example = new ApiExecutionQueueExample();
example.createCriteria().andIdIn(queueIdList);
apiExecutionQueueMapper.deleteByExample(example);
}
}
public void deleteApiExecutionQueueDetail(List<String> queueIdList) {
if (CollectionUtils.isNotEmpty(queueIdList)) {
ApiExecutionQueueDetailExample example = new ApiExecutionQueueDetailExample();
example.createCriteria().andQueueIdIn(queueIdList);
apiExecutionQueueDetailMapper.deleteByExample(example);
}
} }
public String getLastReportByPlanId(String planId) { public String getLastReportByPlanId(String planId) {

View File

@ -16,11 +16,29 @@ public class BatchProcessingUtil {
private static final int BATCH_PROCESS_QUANTITY = 100; private static final int BATCH_PROCESS_QUANTITY = 100;
//批量处理参数是List<String>的函数
public static void consumerByStringList(List<String> stringList, Consumer<List<String>> consumer) {
if (CollectionUtils.isNotEmpty(stringList)) {
int foreachIndex = 0;
int foreachCount = stringList.size() / BATCH_PROCESS_QUANTITY;
while (BATCH_PROCESS_QUANTITY < stringList.size() || (foreachIndex > foreachCount)) {
List<String> handleList = stringList.subList(0, BATCH_PROCESS_QUANTITY);
consumer.accept(handleList);
stringList.removeAll(handleList);
//记录循环次数,防止出现死循环
foreachIndex++;
}
//处理剩余数据
if (CollectionUtils.isNotEmpty(stringList)) {
consumer.accept(stringList);
}
}
}
public static void batchDeleteApiReport(List<String> testPlanReportIdList, Consumer<List<String>> deleteApiCaseReportFunc, Consumer<List<String>> deleteScenarioReportFunc, Consumer<List<String>> deleteUiReportFunc) { public static void batchDeleteApiReport(List<String> testPlanReportIdList, Consumer<List<String>> deleteApiCaseReportFunc, Consumer<List<String>> deleteScenarioReportFunc, Consumer<List<String>> deleteUiReportFunc) {
if (CollectionUtils.isNotEmpty(testPlanReportIdList)) { if (CollectionUtils.isNotEmpty(testPlanReportIdList)) {
int unDeleteReportIdCount = testPlanReportIdList.size(); int unDeleteReportIdCount = testPlanReportIdList.size();
while (BATCH_PROCESS_QUANTITY < testPlanReportIdList.size()) { while (BATCH_PROCESS_QUANTITY < testPlanReportIdList.size()) {
List<String> deleteReportIds = testPlanReportIdList.subList(0, BATCH_PROCESS_QUANTITY); List<String> deleteReportIds = testPlanReportIdList.subList(0, BATCH_PROCESS_QUANTITY);
deleteApiCaseReportFunc.accept(deleteReportIds); deleteApiCaseReportFunc.accept(deleteReportIds);