Pārlūkot izejas kodu

fix: handle api test edge cases

weipengtao 3 mēneši atpakaļ
vecāks
revīzija
01e3100589

+ 42 - 24
web/src/main/java/cn/seecoder/web/service/impl/apitest/ApiTestServiceImpl.java

@@ -5,7 +5,6 @@ import cn.seecoder.common.util.OpType;
 import cn.seecoder.web.dao.apitest.ApiTestMapper;
 import cn.seecoder.web.dao.pipeline.PipelineMapper;
 import cn.seecoder.web.dao.pipeline.PipelineRecordMapper;
-import cn.seecoder.web.dao.user.UserMapper;
 import cn.seecoder.web.model.po.apitest.ApiTestInfo;
 import cn.seecoder.web.model.po.apitest.ApiTestResult;
 import cn.seecoder.web.model.po.apitest.TestInfo;
@@ -42,6 +41,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
 @Service
@@ -54,15 +54,12 @@ public class ApiTestServiceImpl implements ApiTestService {
 
 	private final PipelineRecordMapper pipelineRecordMapper;
 
-	private final UserMapper userMapper;
-
 	@Autowired
 	public ApiTestServiceImpl(ApiTestMapper apiTestMapper, PipelineMapper pipelineMapper,
-							  PipelineRecordMapper pipelineRecordMapper, UserMapper userMapper) {
+							  PipelineRecordMapper pipelineRecordMapper) {
 		this.apiTestMapper = apiTestMapper;
 		this.pipelineMapper = pipelineMapper;
 		this.pipelineRecordMapper = pipelineRecordMapper;
-		this.userMapper = userMapper;
 	}
 
 
@@ -101,6 +98,10 @@ public class ApiTestServiceImpl implements ApiTestService {
 	@Override
 	public void executeApiTest(Integer testId) throws InterruptedException {
 		TestInfo testInfo = apiTestMapper.selectByTestId(testId);
+		if (testInfo == null) {
+			log.warn("API test not found, testId={}", testId);
+			return;
+		}
 		String url = testInfo.getUrl();
 		Map<String, Object> params = parseJson2Map(testInfo.getParams());
 		int qps = testInfo.getQps();
@@ -108,10 +109,12 @@ public class ApiTestServiceImpl implements ApiTestService {
 		Integer projectId = testInfo.getProjectId();
 		//
 
-		if (method.equals("GET")) { // GET方法
+		if ("GET".equals(method)) { // GET方法
 			handleRequest(url, params, qps, testId, "GET", projectId);
-		} else if (method.equals("POST")) { // POST方法
+		} else if ("POST".equals(method)) { // POST方法
 			handleRequest(url, params, qps, testId, "POST", projectId);
+		} else {
+			log.warn("Unsupported API test method, testId={}, method={}", testId, method);
 		}
 		// ANA 日志需要打出测试信息和执行结果,具体信息在handleRequest方法内
 
@@ -121,6 +124,10 @@ public class ApiTestServiceImpl implements ApiTestService {
 	public List<ApiTestResultVO> getApiTestResultByTestId(Integer testId) {
 
 		TestInfo testInfo = apiTestMapper.selectByTestId(testId);
+		if (testInfo == null) {
+			log.warn("API test not found, testId={}", testId);
+			return Collections.emptyList();
+		}
 
 		// 获取最新的部署构建信息id
 		List<Integer> pipelineIds = pipelineMapper.selectByProjectId(testInfo.getProjectId()).stream().map(PipelinePO::getId).collect(Collectors.toList());
@@ -142,6 +149,10 @@ public class ApiTestServiceImpl implements ApiTestService {
 	@Override
 	public ApiTestResultVO getLatestTestResultByTestId(Integer testId) {
 		TestInfo testInfo = apiTestMapper.selectByTestId(testId);
+		if (testInfo == null) {
+			log.warn("API test not found, testId={}", testId);
+			return null;
+		}
 
 		List<Integer> pipelineIds = pipelineMapper.selectByProjectId(testInfo.getProjectId()).stream().map(PipelinePO::getId).collect(Collectors.toList());
 		PipelineRecordPO latestRecord;
@@ -211,7 +222,7 @@ public class ApiTestServiceImpl implements ApiTestService {
 	// 分隔字符串
 	public List<Integer> splitTimeList(String time) {
 		List<Integer> timeList = new ArrayList<>();
-		if (time.length() == 0) {
+		if (time.isEmpty()) {
 			return timeList;
 		}
 		String[] tl = time.split(",");
@@ -223,15 +234,20 @@ public class ApiTestServiceImpl implements ApiTestService {
 
 	// 处理请求
 	public void handleRequest(String url, Map<String, Object> params, int qps, int testId, String method, Integer projectId) throws InterruptedException {
-		ArrayList<Integer> timeList = new ArrayList<>();
-		final int[] success = {0};
-		final int[] failure = {0};
+		if (qps <= 0) {
+			log.warn("Invalid API test qps, testId={}, qps={}", testId, qps);
+			qps = 1;
+		}
+		List<Integer> timeList = Collections.synchronizedList(new ArrayList<>());
+		AtomicInteger success = new AtomicInteger();
+		AtomicInteger failure = new AtomicInteger();
+		AtomicInteger remainingRequests = new AtomicInteger(qps);
 		Runnable task = () -> {
-			for (int i = 0; i < qps / 10; i++) {
+			while (remainingRequests.getAndDecrement() > 0) {
 				int[] arr = new int[2];
-				if (method.equals("GET")) {
+				if ("GET".equals(method)) {
 					arr = doGet(url, params);
-				} else if (method.equals("POST")) {
+				} else if ("POST".equals(method)) {
 					try {
 						arr = doPost(url, params);
 					} catch (IOException e) {
@@ -239,8 +255,8 @@ public class ApiTestServiceImpl implements ApiTestService {
 					}
 				}
 				timeList.add(arr[1]);
-				if (arr[0] == 1) success[0]++;
-				else failure[0]++;
+				if (arr[0] == 1) success.incrementAndGet();
+				else failure.incrementAndGet();
 				try {
 					Thread.sleep(100);
 				} catch (InterruptedException e) {
@@ -250,12 +266,13 @@ public class ApiTestServiceImpl implements ApiTestService {
 			}
 		};
 		startTaskAllInOnce(10, task);
-		Integer max_time = Collections.max(timeList);
-		Integer min_time = Collections.min(timeList);
-		Integer sum_time = 0;
+		Integer max_time = timeList.isEmpty() ? 0 : Collections.max(timeList);
+		Integer min_time = timeList.isEmpty() ? 0 : Collections.min(timeList);
+		int sum_time = 0;
 		for (Integer time : timeList) {
 			sum_time += time;
 		}
+		double averageTime = timeList.isEmpty() ? 0.0 : (double) sum_time / timeList.size();
 		DecimalFormat df = new DecimalFormat("#.00");
 		StringBuilder tl = new StringBuilder();
 		for (int j = 0; j < timeList.size(); j++) {
@@ -278,12 +295,12 @@ public class ApiTestServiceImpl implements ApiTestService {
 		TestResult testResult = TestResult.builder()
 				.testId(testId)
 				.executeTime(executeTime)
-				.success(success[0])
-				.failure(failure[0])
+				.success(success.get())
+				.failure(failure.get())
 				.timeList(tl.toString())
 				.maxTime(max_time)
 				.minTime(min_time)
-				.averageTime((Double.valueOf(df.format(sum_time / qps))))
+				.averageTime(Double.valueOf(df.format(averageTime)))
 				.pipelineRecordId(latestRecord == null ? -1 : latestRecord.getId())
 				.build();
 		apiTestMapper.execute(testResult);
@@ -295,13 +312,14 @@ public class ApiTestServiceImpl implements ApiTestService {
 			object.put("apiTest_id", testId);
 			object.put("project_id", projectId);
 			object.put("user_id", UserService.loginUser().getId());
-			object.put("success", success[0]);
-			object.put("failure", failure[0]);
+			object.put("success", success.get());
+			object.put("failure", failure.get());
 
 			String data = com.alibaba.fastjson.JSONObject.toJSONString(object);
 			LogTrackingUtil.log(data, OpType.INTERFACE_TEST);
 
 		} catch (Exception e) {
+			log.warn("Failed to track API test execution, testId={}", testId, e);
 		}
 	}
 

+ 33 - 80
web/src/main/java/cn/seecoder/web/service/impl/commit/CommitLinkServiceImpl.java

@@ -63,7 +63,7 @@ public class CommitLinkServiceImpl implements CommitLinkService {
 			// ANA 日志需要打出用户的commit信息
 			JSONObject object = new JSONObject();
 			try {
-				object.put("user_id", userMapper.selectIdByEmail(commit.getAuthor().getEmail()) == null ? -1 : userMapper.selectIdByEmail(commit.getAuthor().getEmail()));
+				object.put("user_id", getUserIdByEmail(commit.getAuthor().getEmail()));
 				object.put("commit_id", commit.getId() == null ? -1 : commit.getId());
 				object.put("project_id", projectId == null ? -1 : projectId);
 				object.put("commit_time", commit.getTimestamp());
@@ -80,12 +80,7 @@ public class CommitLinkServiceImpl implements CommitLinkService {
 			if (rule == null) {
 				log.info("Commits 不符合规范, id: {}", commit.getId());
 				// ANA
-				try {
-					object.put("type", "不合规范");
-					String data = JSONObject.toJSONString(object);
-					LogTrackingUtil.log(data, OpType.COMMIT);
-				} catch (Exception ignored) {
-				}
+				trackCommitLog(object, "不合规范");
 				continue;
 			}
 			switch (rule.getType()) {
@@ -94,104 +89,44 @@ public class CommitLinkServiceImpl implements CommitLinkService {
 					this.saveLinkedCommit(new CommitPO(commit, projectId, CommitRelatedEnum.TREE_ID, rule.getId()));
 					log.info("Commits 关联tree节点, id: {}", commit.getId());
 					// ANA
-					try {
-						object.put("type", "关联tree");
-						String data = JSONObject.toJSONString(object);
-						LogTrackingUtil.log(data, OpType.COMMIT);
-					} catch (Exception ignored) {
-					}
+					trackCommitLog(object, "关联tree");
 					break;
 				case FIX:
 					bugListService.updateState(rule.getState(), rule.getId());
 					this.saveLinkedCommit(new CommitPO(commit, projectId, CommitRelatedEnum.BUG_ID, rule.getId()));
 					log.info("Commits 关联bug节点, id: {}", commit.getId());
 					// ANA
-					try {
-						object.put("type", "关联bug");
-						String data = JSONObject.toJSONString(object);
-						LogTrackingUtil.log(data, OpType.COMMIT);
-					} catch (Exception ignored) {
-					}
+					trackCommitLog(object, "关联bug");
 					break;
 				case CI:
-					try {
-						object.put("type", "ci");
-						String data = JSONObject.toJSONString(object);
-						LogTrackingUtil.log(data, OpType.COMMIT);
-					} catch (Exception ignored) {
-					}
+					trackCommitLog(object, "ci");
 					break;
 				case DOCS:
-					try {
-						object.put("type", "docs");
-						String data = JSONObject.toJSONString(object);
-						LogTrackingUtil.log(data, OpType.COMMIT);
-					} catch (Exception ignored) {
-					}
+					trackCommitLog(object, "docs");
 					break;
 				case PERF:
-					try {
-						object.put("type", "perf");
-						String data = JSONObject.toJSONString(object);
-						LogTrackingUtil.log(data, OpType.COMMIT);
-					} catch (Exception ignored) {
-					}
+					trackCommitLog(object, "perf");
 					break;
 				case TEST:
-					try {
-						object.put("type", "test");
-						String data = JSONObject.toJSONString(object);
-						LogTrackingUtil.log(data, OpType.COMMIT);
-					} catch (Exception ignored) {
-					}
+					trackCommitLog(object, "test");
 					break;
 				case BUILD:
-					try {
-						object.put("type", "build");
-						String data = JSONObject.toJSONString(object);
-						LogTrackingUtil.log(data, OpType.COMMIT);
-					} catch (Exception ignored) {
-					}
+					trackCommitLog(object, "build");
 					break;
 				case CHORE:
-					try {
-						object.put("type", "chore");
-						String data = JSONObject.toJSONString(object);
-						LogTrackingUtil.log(data, OpType.COMMIT);
-					} catch (Exception ignored) {
-					}
+					trackCommitLog(object, "chore");
 					break;
 				case STYLE:
-					try {
-						object.put("type", "style");
-						String data = JSONObject.toJSONString(object);
-						LogTrackingUtil.log(data, OpType.COMMIT);
-					} catch (Exception ignored) {
-					}
+					trackCommitLog(object, "style");
 					break;
 				case REVERT:
-					try {
-						object.put("type", "revert");
-						String data = JSONObject.toJSONString(object);
-						LogTrackingUtil.log(data, OpType.COMMIT);
-					} catch (Exception ignored) {
-					}
+					trackCommitLog(object, "revert");
 					break;
 				case REFACTOR:
-					try {
-						object.put("type", "refactor");
-						String data = JSONObject.toJSONString(object);
-						LogTrackingUtil.log(data, OpType.COMMIT);
-					} catch (Exception ignored) {
-					}
+					trackCommitLog(object, "refactor");
 					break;
 				case UNKNOWN:
-					try {
-						object.put("type", "不合规范");
-						String data = JSONObject.toJSONString(object);
-						LogTrackingUtil.log(data, OpType.COMMIT);
-					} catch (Exception ignored) {
-					}
+					trackCommitLog(object, "不合规范");
 					break;
 			}
 		}
@@ -203,7 +138,7 @@ public class CommitLinkServiceImpl implements CommitLinkService {
 		// ANA 日志需要打出用户commit的信息
 		try {
 			JSONObject object = new JSONObject();
-			object.put("user_id", userMapper.selectIdByEmail(po.getEmail()) == null ? -1 : userMapper.selectIdByEmail(po.getEmail()));
+			object.put("user_id", getUserIdByEmail(po.getEmail()));
 			object.put("commit_id", po.getId() == null ? -1 : po.getId());
 			object.put("project_id", po.getProjectId() == null ? -1 : po.getProjectId());
 			object.put("commit_name", po.getGitlabUsername() == null ? -1 : po.getGitlabUsername());
@@ -220,6 +155,24 @@ public class CommitLinkServiceImpl implements CommitLinkService {
 		commitMapper.insert(po);
 	}
 
+	private int getUserIdByEmail(String email) {
+		if (email == null) {
+			return -1;
+		}
+		Integer userId = userMapper.selectIdByEmail(email);
+		return userId == null ? -1 : userId;
+	}
+
+	private void trackCommitLog(JSONObject object, String type) {
+		try {
+			object.put("type", type);
+			String data = JSONObject.toJSONString(object);
+			LogTrackingUtil.log(data, OpType.COMMIT);
+		} catch (Exception e) {
+			log.warn("Failed to track commit log, type={}", type, e);
+		}
+	}
+
 	@Override
 	public boolean isLinked(String id) {
 		return 1 == commitMapper.isExist(id);

+ 8 - 6
web/src/main/java/cn/seecoder/web/service/impl/devmanage/DevmanageServiceImpl.java

@@ -57,9 +57,9 @@ public class DevmanageServiceImpl implements DevmanageService {
 		List<DeploymentPO> deploymentPOList = deploymentMapper.selectByNamespace(namespace);
 		if (deploymentPOList.isEmpty()) {
 			return null;
-		} else {
-			return new UserVO(getUserPO(deploymentPOList.get(0)));
 		}
+		UserPO userPO = getUserPO(deploymentPOList.get(0));
+		return userPO == null ? null : new UserVO(userPO);
 	}
 
 //    @Transactional(readOnly = true)
@@ -77,6 +77,9 @@ public class DevmanageServiceImpl implements DevmanageService {
 	}
 
 	private boolean isInvalidPageSize(Integer pageSize) {
+		if (pageSize == null) {
+			return true;
+		}
 		for (int validPageSize : validPageSizes) {
 			if (validPageSize == pageSize) {
 				return false;
@@ -88,11 +91,10 @@ public class DevmanageServiceImpl implements DevmanageService {
 	private UserPO getUserPO(DeploymentPO deploymentPO) {
 		Integer pipelineId = deploymentPO.getPipelineId();
 		List<PipelineRecordPO> pipelineRecordPOS = pipelineRecordMapper.selectByPipelineId(pipelineId);
-		if (pipelineRecordPOS.size() == 0) {
+		if (pipelineRecordPOS.isEmpty()) {
 			return null;
-		} else {
-			Integer userId = pipelineRecordPOS.get(0).getUserId();
-			return userMapper.select(userId);
 		}
+		Integer userId = pipelineRecordPOS.get(0).getUserId();
+		return userMapper.select(userId);
 	}
 }