This commit is contained in:
张良(004796)
2024-01-25 17:16:23 +08:00
parent 31036e69af
commit 7874e38d17
19 changed files with 326 additions and 415 deletions

View File

@@ -1,81 +0,0 @@
package com.ruoyi.cai.ws.job;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.cai.domain.UserCall;
import com.ruoyi.cai.service.UserCallService;
import com.ruoyi.cai.trd.ImDataRes;
import com.ruoyi.cai.trd.ImMsgGen;
import com.ruoyi.cai.ws.bean.Room;
import com.ruoyi.cai.ws.bean.UserData;
import com.ruoyi.cai.ws.cache.OnlineDataCache;
import com.ruoyi.cai.ws.constant.RoomStatusEnums;
import com.ruoyi.cai.ws.service.RoomService;
import com.ruoyi.cai.ws.service.SettleService;
import com.ruoyi.yunxin.Yunxin;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Set;
@Component
@Slf4j
public class CheckTimeOutJob {
@Autowired
private OnlineDataCache onlineDataCache;
@Autowired
private RoomService roomService;
@Autowired
private UserCallService userCallService;
@Autowired
private SettleService settleService;
@Autowired
private Yunxin yunxin;
/**
* 检查房间是不是三分钟没有接听, 需要自动挂断掉
*/
// @Scheduled(fixedDelay = 60,timeUnit = TimeUnit.SECONDS)
public void run(){
Set<String> roomIdStr = onlineDataCache.getAll();
for (String roomIdS : roomIdStr) {
Long roomId = Long.valueOf(roomIdS);
this.deal(roomId);
}
}
public void deal(Long roomId){
log.info("开始执行房间超时检测,是否一直不接 roomId={}",roomId);
Room room = roomService.load(roomId);
if(room == null){
return;
}
if(!RoomStatusEnums.STATUS_CALLER_CONNECT.getCode().equals(room.getStatus())
&& !RoomStatusEnums.STATUS_RECEIVER_CONNECT.getCode().equals(room.getStatus())){
return;
}
UserData callUserData = room.getCallUserData();
UserData receiverUserData = room.getReceiverUserData();
// 检测是不是3分钟没有接听
Long connectTimeCaller = callUserData.getConnectTime();
Long connectTimeReceiver = receiverUserData.getConnectTime();
boolean timeOut = false;
if(connectTimeCaller != null && DateUtil.currentSeconds() - connectTimeCaller > 180){
timeOut = true;
}else if(connectTimeReceiver != null && DateUtil.currentSeconds() - connectTimeReceiver > 180){
timeOut = true;
}
if(timeOut){
if(roomService.hangUp(roomId)){
userCallService.update(Wrappers.lambdaUpdate(UserCall.class)
.eq(UserCall::getId,roomId)
.set(UserCall::getStatus, RoomStatusEnums.STATUS_TIMEOUT_CANCEL.getCode()));
// TODO 需要放开主播的接听状态
roomService.closeAllFd(roomId);
ImDataRes imDataRes = ImMsgGen.callNotice(3, callUserData.getId(), receiverUserData.getId(), 0);
yunxin.sendToSync(receiverUserData.getId(),callUserData.getId(),imDataRes);
}
}
}
}

View File

@@ -1,102 +0,0 @@
package com.ruoyi.cai.ws.job;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.cai.domain.UserCall;
import com.ruoyi.cai.service.UserCallService;
import com.ruoyi.cai.ws.bean.Room;
import com.ruoyi.cai.ws.bean.UserData;
import com.ruoyi.cai.ws.cache.OnlineDataCache;
import com.ruoyi.cai.ws.cache.RoomCtxCache;
import com.ruoyi.cai.ws.constant.HangUpEnums;
import com.ruoyi.cai.ws.constant.RoomStatusEnums;
import com.ruoyi.cai.ws.dto.WsR;
import com.ruoyi.cai.ws.dto.WsRMsgGen;
import com.ruoyi.cai.ws.service.RoomService;
import com.ruoyi.cai.ws.service.SettleService;
import com.ruoyi.cai.ws.util.RoomWebSocketUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class HeartbeatJob {
@Autowired
private OnlineDataCache onlineDataCache;
@Autowired
private RoomService roomService;
@Autowired
private UserCallService userCallService;
@Autowired
private SettleService settleService;
@Autowired
private RoomCtxCache roomCtxCache;
/**
* 30秒执行一次 心跳只处理接听后的心跳
*/
@Scheduled(fixedDelay = 30,timeUnit = TimeUnit.SECONDS)
public void run(){
Set<String> all = onlineDataCache.getAll();
for (String roomIdS : all) {
try {
Long roomId = Long.valueOf(roomIdS);
Room room = roomService.load(roomId);
if(room == null){
return;
}
if(!room.isCanCall()){
return;
}
UserData callUserData = room.getCallUserData();
UserData receiverUserData = room.getReceiverUserData();
boolean timeOut = false;
WsR hangup = null;
if(isHeartTimeout(callUserData)){
timeOut = true;
hangup = WsRMsgGen.hangup("呼叫方连接中断", roomId, HangUpEnums.FROM.getCode());
}else if(isHeartTimeout(receiverUserData)){
timeOut = true;
hangup = WsRMsgGen.hangup("接听方连接中断", roomId, HangUpEnums.TO.getCode());
}
if(timeOut){
if(roomService.hangUp(roomId)){
userCallService.update(Wrappers.lambdaUpdate(UserCall.class)
.eq(UserCall::getId,roomId)
.set(UserCall::getStatus, RoomStatusEnums.STATUS_TIMEOUT_CANCEL.getCode()));
settleService.processOn(roomId);
}
List<String> keys = roomCtxCache.getSessionKeysByRoomId(roomId);
RoomWebSocketUtil.sendSendMessage(keys, hangup);
roomService.closeAllFd(roomId);
}
}catch (Exception e){
log.error("定时心跳检测失败!",e);
}
}
}
/**
* 是否心跳超时
* @param userData
* @return
*/
private boolean isHeartTimeout(UserData userData){
if(userData.getConnectTime() == null){
return false;
}
if(DateUtil.currentSeconds() - userData.getHeartTime() < 120){
return false;
}
return true;
}
}

View File

@@ -1,158 +1,37 @@
package com.ruoyi.cai.ws.job;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.cai.domain.UserCall;
import com.ruoyi.cai.service.UserCallService;
import com.ruoyi.cai.trd.ImDataRes;
import com.ruoyi.cai.trd.ImMsgGen;
import com.ruoyi.cai.ws.bean.Room;
import com.ruoyi.cai.ws.bean.UserData;
import com.ruoyi.cai.ws.cache.RoomCtxCache;
import com.ruoyi.cai.ws.constant.HangUpEnums;
import com.ruoyi.cai.ws.constant.RoomStatusEnums;
import com.ruoyi.cai.ws.dto.WsR;
import com.ruoyi.cai.ws.dto.WsRMsgGen;
import com.ruoyi.cai.ws.cache.OnlineDataCache;
import com.ruoyi.cai.ws.service.RoomService;
import com.ruoyi.cai.ws.service.SettleResp;
import com.ruoyi.cai.ws.service.SettleService;
import com.ruoyi.cai.ws.util.RoomWebSocketUtil;
import com.ruoyi.yunxin.Yunxin;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class RoomCheckJob {
@Autowired
private RoomService roomService;
private OnlineDataCache onlineDataCache;
@Autowired
private UserCallService userCallService;
@Autowired
private Yunxin yunxin;
@Autowired
private SettleService settleService;
@Autowired
private RoomCtxCache roomCtxCache;
public JobResp checkRoom(Long roomId){
Room room = roomService.load(roomId);
if(room == null){
return JobResp.builder().nextCreateJob(false).build();
}
// 检查是否三分钟没有接听
JobResp resp = this.checkRoomCallerTimeOut(room);
if(!resp.isNextCreateJob()){
return resp;
}
// 检查心跳
JobResp heartbeat = checkRoomHeartbeat(room);
if(!heartbeat.isNextCreateJob()){
return heartbeat;
}
this.checkCanCallTime(room);
// 尝试结算一下
SettleResp settleResp = settleService.processOn(roomId);
return JobResp.builder().nextCreateJob(settleResp.isNextRun()).build();
}
private void checkCanCallTime(Room room){
Long time = roomService.canCallTime(room);
if(time < 150 && time > 60){ // 提示余额不足
String sessionKey = roomCtxCache.getSessionKeyCallerByRoomId(room.getRoomId());
RoomWebSocketUtil.sendSendMessage(sessionKey, WsRMsgGen.rechargeNotice("您的余额不足,点此充值"));
}
}
private JobResp checkRoomHeartbeat(Room room){
if(!room.isCanCall()){
return JobResp.builder().nextCreateJob(true).build();
}
Long roomId = room.getRoomId();
UserData callUserData = room.getCallUserData();
UserData receiverUserData = room.getReceiverUserData();
boolean timeOut = false;
WsR hangup = null;
if(isHeartTimeout(callUserData)){
timeOut = true;
hangup = WsRMsgGen.hangup("呼叫方连接中断", roomId, HangUpEnums.FROM.getCode());
}else if(isHeartTimeout(receiverUserData)){
timeOut = true;
hangup = WsRMsgGen.hangup("接听方连接中断", roomId, HangUpEnums.TO.getCode());
}
if(timeOut){
boolean nextCreateJob = false;
if(roomService.hangUp(roomId)){
userCallService.update(Wrappers.lambdaUpdate(UserCall.class)
.eq(UserCall::getId,roomId)
.set(UserCall::getStatus, RoomStatusEnums.STATUS_TIMEOUT_CANCEL.getCode()));
SettleResp settleResp = settleService.processOn(roomId);
nextCreateJob = settleResp.isNextRun();
}
List<String> keys = roomCtxCache.getSessionKeysByRoomId(roomId);
RoomWebSocketUtil.sendSendMessage(keys, hangup);
roomService.closeAllFd(roomId);
return JobResp.builder().nextCreateJob(nextCreateJob).build();
}
return JobResp.builder().nextCreateJob(true).build();
}
// 检测是不是3分钟没有接听
private JobResp checkRoomCallerTimeOut(Room room){
if(RoomStatusEnums.STATUS_CALLER_CONNECT.getCode().equals(room.getStatus())
&& RoomStatusEnums.STATUS_RECEIVER_CONNECT.getCode().equals(room.getStatus())) {
return JobResp.builder().nextCreateJob(true).build();
}
UserData callUserData = room.getCallUserData();
UserData receiverUserData = room.getReceiverUserData();
Long connectTimeCaller = callUserData.getConnectTime();
Long connectTimeReceiver = receiverUserData.getConnectTime();
boolean timeOut = false;
if(connectTimeCaller != null && DateUtil.currentSeconds() - connectTimeCaller > 180){
timeOut = true;
}else if(connectTimeReceiver != null && DateUtil.currentSeconds() - connectTimeReceiver > 180){
timeOut = true;
}
if(timeOut){
Long roomId = room.getRoomId();
boolean nextCreateJob = false;
if(roomService.hangUp(roomId)){
userCallService.update(Wrappers.lambdaUpdate(UserCall.class)
.eq(UserCall::getId,roomId)
.set(UserCall::getStatus, RoomStatusEnums.STATUS_TIMEOUT_CANCEL.getCode()));
SettleResp settleResp = settleService.processOn(roomId);
nextCreateJob = settleResp.isNextRun();
}
roomService.closeAllFd(roomId);
ImDataRes imDataRes = ImMsgGen.callNotice(3, callUserData.getId(), receiverUserData.getId(), 0);
yunxin.sendToSync(receiverUserData.getId(),callUserData.getId(),imDataRes);
return JobResp.builder().nextCreateJob(nextCreateJob).build();
}
return JobResp.builder().nextCreateJob(true).build();
}
private RoomCheckJobService roomCheckJobService;
/**
* 是否心跳超时
* @param userData
* @return
* 每 7分钟执行一次
*/
private boolean isHeartTimeout(UserData userData){
if(userData.getConnectTime() == null){
return false;
@Scheduled(fixedDelay = 7,timeUnit = TimeUnit.MINUTES)
public void run(){
Set<String> all = onlineDataCache.getAll();
for (String roomIdS : all) {
try {
Long roomId = Long.valueOf(roomIdS);
roomCheckJobService.checkRoom(roomId);
}catch (Exception e){
log.info("定时检测房间失败!需要开发排查问题 roomId={}", roomIdS, e);
}
}
if(DateUtil.currentSeconds() - userData.getHeartTime() < 117){
return false;
}
return true;
}
}

View File

@@ -0,0 +1,158 @@
package com.ruoyi.cai.ws.job;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.cai.domain.UserCall;
import com.ruoyi.cai.service.UserCallService;
import com.ruoyi.cai.trd.ImDataRes;
import com.ruoyi.cai.trd.ImMsgGen;
import com.ruoyi.cai.ws.bean.Room;
import com.ruoyi.cai.ws.bean.UserData;
import com.ruoyi.cai.ws.cache.RoomCtxCache;
import com.ruoyi.cai.ws.constant.HangUpEnums;
import com.ruoyi.cai.ws.constant.RoomStatusEnums;
import com.ruoyi.cai.ws.dto.WsR;
import com.ruoyi.cai.ws.dto.WsRMsgGen;
import com.ruoyi.cai.ws.service.RoomService;
import com.ruoyi.cai.ws.service.SettleResp;
import com.ruoyi.cai.ws.service.SettleService;
import com.ruoyi.cai.ws.util.RoomWebSocketUtil;
import com.ruoyi.yunxin.Yunxin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class RoomCheckJobService {
@Autowired
private RoomService roomService;
@Autowired
private UserCallService userCallService;
@Autowired
private Yunxin yunxin;
@Autowired
private SettleService settleService;
@Autowired
private RoomCtxCache roomCtxCache;
public JobResp checkRoom(Long roomId){
Room room = roomService.load(roomId);
if(room == null){
return JobResp.builder().nextCreateJob(false).build();
}
// 检查是否三分钟没有接听
JobResp resp = this.checkRoomCallerTimeOut(room);
if(!resp.isNextCreateJob()){
return resp;
}
// 检查心跳
JobResp heartbeat = checkRoomHeartbeat(room);
if(!heartbeat.isNextCreateJob()){
return heartbeat;
}
this.checkCanCallTime(room);
// 尝试结算一下
SettleResp settleResp = settleService.processOn(roomId);
return JobResp.builder().nextCreateJob(settleResp.isNextRun()).build();
}
private void checkCanCallTime(Room room){
Long time = roomService.canCallTime(room);
if(time < 150 && time > 60){ // 提示余额不足
String sessionKey = roomCtxCache.getSessionKeyCallerByRoomId(room.getRoomId());
RoomWebSocketUtil.sendSendMessage(sessionKey, WsRMsgGen.rechargeNotice("您的余额不足,点此充值"));
}
}
private JobResp checkRoomHeartbeat(Room room){
if(!room.isCanCall()){
return JobResp.builder().nextCreateJob(true).build();
}
Long roomId = room.getRoomId();
UserData callUserData = room.getCallUserData();
UserData receiverUserData = room.getReceiverUserData();
boolean timeOut = false;
WsR hangup = null;
if(isHeartTimeout(callUserData)){
timeOut = true;
hangup = WsRMsgGen.hangup("呼叫方连接中断", roomId, HangUpEnums.FROM.getCode());
}else if(isHeartTimeout(receiverUserData)){
timeOut = true;
hangup = WsRMsgGen.hangup("接听方连接中断", roomId, HangUpEnums.TO.getCode());
}
if(timeOut){
boolean nextCreateJob = false;
if(roomService.hangUp(roomId)){
userCallService.update(Wrappers.lambdaUpdate(UserCall.class)
.eq(UserCall::getId,roomId)
.set(UserCall::getStatus, RoomStatusEnums.STATUS_TIMEOUT_CANCEL.getCode()));
SettleResp settleResp = settleService.processOn(roomId);
nextCreateJob = settleResp.isNextRun();
}
List<String> keys = roomCtxCache.getSessionKeysByRoomId(roomId);
RoomWebSocketUtil.sendSendMessage(keys, hangup);
roomService.closeAllFd(roomId);
return JobResp.builder().nextCreateJob(nextCreateJob).build();
}
return JobResp.builder().nextCreateJob(true).build();
}
// 检测是不是3分钟没有接听
private JobResp checkRoomCallerTimeOut(Room room){
if(RoomStatusEnums.STATUS_CALLER_CONNECT.getCode().equals(room.getStatus())
&& RoomStatusEnums.STATUS_RECEIVER_CONNECT.getCode().equals(room.getStatus())) {
return JobResp.builder().nextCreateJob(true).build();
}
UserData callUserData = room.getCallUserData();
UserData receiverUserData = room.getReceiverUserData();
Long connectTimeCaller = callUserData.getConnectTime();
Long connectTimeReceiver = receiverUserData.getConnectTime();
boolean timeOut = false;
if(connectTimeCaller != null && DateUtil.currentSeconds() - connectTimeCaller > 180){
timeOut = true;
}else if(connectTimeReceiver != null && DateUtil.currentSeconds() - connectTimeReceiver > 180){
timeOut = true;
}
if(timeOut){
Long roomId = room.getRoomId();
boolean nextCreateJob = false;
if(roomService.hangUp(roomId)){
userCallService.update(Wrappers.lambdaUpdate(UserCall.class)
.eq(UserCall::getId,roomId)
.set(UserCall::getStatus, RoomStatusEnums.STATUS_TIMEOUT_CANCEL.getCode()));
SettleResp settleResp = settleService.processOn(roomId);
nextCreateJob = settleResp.isNextRun();
}
roomService.closeAllFd(roomId);
ImDataRes imDataRes = ImMsgGen.callNotice(3, callUserData.getId(), receiverUserData.getId(), 0);
yunxin.sendToSync(receiverUserData.getId(),callUserData.getId(),imDataRes);
return JobResp.builder().nextCreateJob(nextCreateJob).build();
}
return JobResp.builder().nextCreateJob(true).build();
}
/**
* 是否心跳超时
* @param userData
* @return
*/
private boolean isHeartTimeout(UserData userData){
if(userData.getConnectTime() == null){
return false;
}
if(DateUtil.currentSeconds() - userData.getHeartTime() < 117){
return false;
}
return true;
}
}

View File

@@ -1,40 +0,0 @@
package com.ruoyi.cai.ws.job;
import com.ruoyi.cai.ws.bean.Room;
import com.ruoyi.cai.ws.cache.OnlineDataCache;
import com.ruoyi.cai.ws.service.RoomService;
import com.ruoyi.cai.ws.service.SettleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class SettleJob {
@Autowired
private OnlineDataCache onlineDataCache;
@Autowired
private SettleService settleService;
@Autowired
private RoomService roomService;
/**
* 每 1 分钟执行一次
*/
// @Scheduled(fixedDelay = 60,timeUnit = TimeUnit.SECONDS)
public void run(){
Set<String> all = onlineDataCache.getAll();
for (String roomIdS : all) {
try {
Long roomId = Long.valueOf(roomIdS);
settleService.processOn(roomId);
}catch (Exception e){
log.info("定时任务结算失败!",e);
}
}
}
}