Skip to content

Commit

Permalink
bugfix:用例丢失问题修复
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaofeng committed Sep 9, 2021
1 parent 3407027 commit 20b4d42
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.xiaoju.framework.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xiaoju.framework.entity.persistent.CaseBackup;
import com.xiaoju.framework.entity.persistent.TestCase;
import com.xiaoju.framework.util.BitBaseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -44,13 +47,25 @@ protected void internalRemovePlayer(Player p) {
}
synchronized (WebSocket.getRoomLock()) {
if (testCaseContent != null) {
testCase.setCaseContent(testCaseContent);
testCase.setGmtModified(new Date(System.currentTimeMillis()));
int ret = caseMapper.update(testCase);
if (ret < 1) {
LOGGER.error(Thread.currentThread().getName() + ": 数据库用例内容更新失败。 ret = " + ret);
LOGGER.error("应该保存的用例内容是:" + testCaseContent);
TestCase testCaseBase = caseMapper.selectOne(testCase.getId());


JSONObject caseContentToSave = JSON.parseObject(testCaseContent);
JSONObject caseContentBase = JSON.parseObject(testCaseBase.getCaseContent());
if (caseContentToSave.getInteger("base") > caseContentBase.getInteger("base")) {
// 保存落库
testCase.setCaseContent(testCaseContent);
testCase.setGmtModified(new Date(System.currentTimeMillis()));
int ret = caseMapper.update(testCase);
if (ret < 1) {
LOGGER.error(Thread.currentThread().getName() + ": 数据库用例内容更新失败。 ret = " + ret);
LOGGER.error("应该保存的用例内容是:" + testCaseContent);
}
} else {
// 不保存
LOGGER.info(Thread.currentThread().getName() + "不落库." + testCaseContent );
}

}
WebSocket.getRooms().remove(Long.valueOf(BitBaseUtil.mergeLong(0l, Long.valueOf(testCase.getId()))));
LOGGER.info(Thread.currentThread().getName() + ": [websocket-onClose 关闭当前Room成功]当前sessionid:" + p.getClient().getSession().getId());
Expand All @@ -61,5 +76,7 @@ protected void internalRemovePlayer(Player p) {

// 广播有用户离开
broadcastRoomMessage(CaseMessageType.NOTIFY, "当前用户数:" + players.size() + "。用例编辑者 " + p.getClient().getClientName() + " 离开");
LOGGER.info(Thread.currentThread().getName() + ": 用例保存完成。");

}
}
19 changes: 16 additions & 3 deletions case-server/src/main/java/com/xiaoju/framework/handler/Room.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@
import com.xiaoju.framework.service.CaseBackupService;
import com.xiaoju.framework.service.RecordService;
import com.xiaoju.framework.util.BitBaseUtil;
import lombok.extern.flogger.Flogger;
import org.apache.poi.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.websocket.Session;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

Expand All @@ -43,14 +41,16 @@ public abstract class Room {
private static final int TIMER_DELAY = 30;
private TimerTask activeBroadcastTimerTask;

private static final int MAX_PLAYER_COUNT = 100;
private static final int MAX_PLAYER_COUNT = 10;
public final List<Player> players = new ArrayList<>();

public final List<String> undoDiffs = new LinkedList<>();
public final List<String> redoDiffs = new LinkedList<>();
private Integer undoPosition;
private Integer redoPosition;

protected Integer lastUndoCounts;

public final Map<Session, Client> cs = new ConcurrentHashMap<>();

public static TestCaseMapper caseMapper;
Expand Down Expand Up @@ -93,6 +93,7 @@ public Room(Long id) {
}
undoPosition = undoDiffs.size();
redoPosition = redoDiffs.size();
lastUndoCounts = 0;
}

private TimerTask createBroadcastTimerTask() {
Expand All @@ -113,6 +114,10 @@ public String getTestCaseContent() {
return testCaseContent;
}

public void setTestCaseContent(String content) {
testCaseContent = content;
}

public Player createAndAddPlayer(Client client) {
if (players.size() >= MAX_PLAYER_COUNT) {
throw new IllegalStateException("Maximum player count ("
Expand Down Expand Up @@ -177,8 +182,10 @@ private void internalHandleMessage(Player p, String msg,
//todo: testCase.apply(msg) 新增如上的方法.
if (msg.endsWith("undo")) {
undo();
lastUndoCounts ++;
} else if (msg.endsWith("redo")) {
redo();
lastUndoCounts --;
} else {
broadcastMessage(msg);

Expand Down Expand Up @@ -231,6 +238,12 @@ private void internalHandleCtrlMessage(String msg) {
}
}

public void leavebroadcastMessageForHttp(String msg) {
for (Player p : players) {
p.getBufferedMessages().add(msg);
}
}

private void broadcastMessage(String msg) {
if (!BUFFER_MESSAGES) {
String msgStr = msg.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.flipkart.zjsonpatch.DiffFlags.ADD_ORIGINAL_VALUE_ON_REPLACE;

Expand All @@ -40,6 +41,8 @@ public class CaseBackupServiceImpl implements CaseBackupService {
@Override
@Transactional(rollbackFor = Exception.class)
public synchronized CaseBackup insertBackup(CaseBackup caseBackup) {
LOGGER.info(Thread.currentThread().getName() + ": 备份保存当前用例。");

// 此处可以与最新的内容比对,如果一致,则不更新backup表,减少版本数量
List<CaseBackup> caseBackups = caseBackupMapper.selectByCaseId(caseBackup.getCaseId(), null, null);

Expand All @@ -50,6 +53,7 @@ public synchronized CaseBackup insertBackup(CaseBackup caseBackup) {
if (caseBackups.size() > 0 &&
JsonDiff.asJson(jsonMapper.readTree(caseBackups.get(0).getCaseContent()),
jsonMapper.readTree(caseBackup.getCaseContent())).size() == 0 &&
(!StringUtils.isEmpty(caseBackups.get(0).getRecordContent())) &&
JsonDiff.asJson(jsonMapper.readTree(caseBackups.get(0).getRecordContent()),
jsonMapper.readTree(caseBackup.getRecordContent())).size() == 0) {
LOGGER.info("当前内容已经保存过了,不再重复保存。");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.flipkart.zjsonpatch.JsonDiff;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xiaoju.framework.constants.SystemConstant;
Expand All @@ -27,6 +33,7 @@
import com.xiaoju.framework.entity.response.controller.PageModule;
import com.xiaoju.framework.entity.response.dir.BizListResp;
import com.xiaoju.framework.entity.response.dir.DirTreeResp;
import com.xiaoju.framework.handler.Room;
import com.xiaoju.framework.handler.WebSocket;
import com.xiaoju.framework.mapper.BizMapper;
import com.xiaoju.framework.mapper.ExecRecordMapper;
Expand Down Expand Up @@ -247,6 +254,8 @@ public void wsSave(WsSaveReq req) {
// throw new CaseServerException("用例ws链接已经断开,当前保存可能丢失,请刷新页面重建ws链接。", StatusCode.WS_UNKNOWN_ERROR);
// }

LOGGER.info(Thread.currentThread().getName() + ": http开始保存用例。");

CaseBackup caseBackup = new CaseBackup();
// 这里触发保存record
if (!StringUtils.isEmpty(req.getRecordId())) {
Expand Down Expand Up @@ -292,21 +301,53 @@ public void wsSave(WsSaveReq req) {
} else {
// 这里触发保存testcase
synchronized (WebSocket.getRoomLock()) {
if (null == WebSocket.getRoom(false, BitBaseUtil.mergeLong(0l, Long.valueOf(req.getId())))) {
TestCase testCase = caseMapper.selectOne(req.getId());
String caseContent = testCase.getCaseContent();

JSONObject caseContentJson = JSON.parseObject(caseContent);
JSONObject caseContentCurrent = JSON.parseObject(req.getCaseContent());
testCase.setModifier(req.getModifier());
if (caseContentJson.getInteger("base") < caseContentCurrent.getInteger("base")) {
testCase.setCaseContent(req.getCaseContent());
TestCase testCase = caseMapper.selectOne(req.getId());
// String caseContent = testCase.getCaseContent();
JSONObject caseContentToSave = JSON.parseObject(req.getCaseContent());
JSONObject caseContentBase = JSON.parseObject(testCase.getCaseContent());
// if (caseContentToSave.getInteger("base") > caseContentBase.getInteger("base")) {
// // 保存落库
//
// } else {
// 保存落库,且发送消息给其他客户端(如果有)
ObjectMapper jsonMapper = new ObjectMapper();
Room room = WebSocket.getRoom(false, BitBaseUtil.mergeLong(0l, Long.valueOf(req.getId())));
if (null != room && room.getTestCaseContent() != null) {
try {
JsonNode baseContent = jsonMapper.readTree(room.getTestCaseContent());
JsonNode reqContent = jsonMapper.readTree(req.getCaseContent());

ArrayNode patches = (ArrayNode) JsonDiff.asJson(baseContent, reqContent);
if (patches.size() > 1) { // 此处待验证
JsonNodeFactory FACTORY = JsonNodeFactory.instance;
ObjectNode basePatch = FACTORY.objectNode();
basePatch.put("op", "replace");
basePatch.put("path", "/base");
basePatch.put("value", reqContent.get("base").asLong() + 1);
patches.add(basePatch);
room.leavebroadcastMessageForHttp(patches.toString());
room.setTestCaseContent(req.getCaseContent());
LOGGER.info("非最后离开, 将变更补丁信息发送给其他用户. req内容是: ", reqContent.toString());
LOGGER.info("room内容是: ", baseContent.toString());
} else {
LOGGER.info("patch太小." + patches.toString());
}
} catch (Exception e) {
LOGGER.error("http保存比较内容失败.", e);
}
caseMapper.update(testCase);
LOGGER.info("当前是最后一个退出, 落库保存用例.");
} else {
LOGGER.info("当前不是最后一个退出, 不落库保存用例.");
LOGGER.info("websocket实例已经退出,无需发送消息.");
}
// }

testCase.setCaseContent(req.getCaseContent());
testCase.setGmtModified(new Date(System.currentTimeMillis()));
int ret = caseMapper.update(testCase);
if (ret < 1) {
LOGGER.error(Thread.currentThread().getName() + ": 数据库用例内容更新失败。http save ret = " + ret);
LOGGER.error("http应该保存的用例内容是:" + req.getCaseContent());
}

}
caseBackup.setCaseId(req.getId());
caseBackup.setCaseContent(req.getCaseContent());
Expand All @@ -315,6 +356,9 @@ public void wsSave(WsSaveReq req) {
caseBackup.setCreator(req.getModifier());
caseBackup.setExtra("");
caseBackupService.insertBackup(caseBackup);

LOGGER.info(Thread.currentThread().getName() + ": http开始保存结束。");

}

/**
Expand Down

0 comments on commit 20b4d42

Please sign in to comment.