Commit 3ed2f983 by 罗长华

Merge remote-tracking branch 'origin/feature-cluster' into feature-cluster

parents cf654e61 69dcde6a
...@@ -2,6 +2,7 @@ package com.wecloud.im.controller; ...@@ -2,6 +2,7 @@ package com.wecloud.im.controller;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.wecloud.im.param.AgreeToMultiMeetParam; import com.wecloud.im.param.AgreeToMultiMeetParam;
import com.wecloud.im.param.HeartbeatMultiMeetParam;
import com.wecloud.im.param.InviteToMultiMeetParam; import com.wecloud.im.param.InviteToMultiMeetParam;
import com.wecloud.im.param.LeaveFromMultiMeetParam; import com.wecloud.im.param.LeaveFromMultiMeetParam;
import com.wecloud.im.param.NotAnsweredMultiMeetParam; import com.wecloud.im.param.NotAnsweredMultiMeetParam;
...@@ -81,5 +82,12 @@ public class ImMultiMeetController extends BaseController { ...@@ -81,5 +82,12 @@ public class ImMultiMeetController extends BaseController {
return ApiResult.ok(); return ApiResult.ok();
} }
@PostMapping("/heartbeat")
@ApiOperation(value = "发送心跳", notes = "发送心跳")
public ApiResult<Boolean> heartbeat(@RequestBody HeartbeatMultiMeetParam param) {
multiMeetService.heartbeat(param);
return ApiResult.ok();
}
} }
...@@ -52,6 +52,9 @@ public class ImMultiRtcRoomMember extends BaseEntity { ...@@ -52,6 +52,9 @@ public class ImMultiRtcRoomMember extends BaseEntity {
@ApiModelProperty("呼叫时间") @ApiModelProperty("呼叫时间")
private Date callTime; private Date callTime;
@ApiModelProperty("心跳时间")
private Date heartbeatTime;
@ApiModelProperty("创建时间") @ApiModelProperty("创建时间")
private Date createTime; private Date createTime;
......
package com.wecloud.im.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Author wenzhida
* @Date 2022/4/1 20:09
* @Description 多人音视频会议发送心跳入参
*/
@Data
@ApiModel(value = "多人音视频会议发送心跳入参")
public class HeartbeatMultiMeetParam implements Serializable {
private static final long serialVersionUID = -5000410376842426276L;
@ApiModelProperty(value = "会话id,可选", required = false)
private Long conversationId;
@ApiModelProperty(value = "多人会议房间id", required = true)
private String roomId;
}
package com.wecloud.im.service; package com.wecloud.im.service;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImMultiRtcRoomMember; import com.wecloud.im.entity.ImMultiRtcRoomMember;
import io.geekidea.springbootplus.framework.common.service.BaseService; import io.geekidea.springbootplus.framework.common.service.BaseService;
...@@ -13,7 +12,7 @@ public interface ImMultiRtcRoomMemberService extends BaseService<ImMultiRtcRoomM ...@@ -13,7 +12,7 @@ public interface ImMultiRtcRoomMemberService extends BaseService<ImMultiRtcRoomM
/** /**
* 改变会议成员状态 * 改变会议成员状态
* @param currentClient * @param fkClientId
* @param roomId * @param roomId
* @param state * @param state
*/ */
......
package com.wecloud.multimeet.service; package com.wecloud.multimeet.service;
import com.wecloud.im.param.AgreeToMultiMeetParam; import com.wecloud.im.param.AgreeToMultiMeetParam;
import com.wecloud.im.param.HeartbeatMultiMeetParam;
import com.wecloud.im.param.InviteToMultiMeetParam; import com.wecloud.im.param.InviteToMultiMeetParam;
import com.wecloud.im.param.LeaveFromMultiMeetParam; import com.wecloud.im.param.LeaveFromMultiMeetParam;
import com.wecloud.im.param.NotAnsweredMultiMeetParam; import com.wecloud.im.param.NotAnsweredMultiMeetParam;
...@@ -45,8 +46,19 @@ public interface MultiMeetService { ...@@ -45,8 +46,19 @@ public interface MultiMeetService {
void notAnswered(NotAnsweredMultiMeetParam param); void notAnswered(NotAnsweredMultiMeetParam param);
/** /**
* 心跳接收
* @param param
*/
void heartbeat(HeartbeatMultiMeetParam param);
/**
* 呼叫超时逻辑处理 * 呼叫超时逻辑处理
*/ */
void callingTimeout(); void callingTimeout();
/**
* 异常断线逻辑处理
*/
void disconnect();
} }
package com.wecloud.multimeet.service.impl; package com.wecloud.multimeet.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.wecloud.im.entity.ImClient; import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImMultiRtcRoom; import com.wecloud.im.entity.ImMultiRtcRoom;
...@@ -8,6 +9,7 @@ import com.wecloud.im.entity.ImMultiRtcRoomMember; ...@@ -8,6 +9,7 @@ import com.wecloud.im.entity.ImMultiRtcRoomMember;
import com.wecloud.im.enums.MultiRtcMemberStateEnum; import com.wecloud.im.enums.MultiRtcMemberStateEnum;
import com.wecloud.im.enums.MultiRtcRoomStateEnum; import com.wecloud.im.enums.MultiRtcRoomStateEnum;
import com.wecloud.im.param.AgreeToMultiMeetParam; import com.wecloud.im.param.AgreeToMultiMeetParam;
import com.wecloud.im.param.HeartbeatMultiMeetParam;
import com.wecloud.im.param.InviteToMultiMeetParam; import com.wecloud.im.param.InviteToMultiMeetParam;
import com.wecloud.im.param.LeaveFromMultiMeetParam; import com.wecloud.im.param.LeaveFromMultiMeetParam;
import com.wecloud.im.param.NotAnsweredMultiMeetParam; import com.wecloud.im.param.NotAnsweredMultiMeetParam;
...@@ -122,6 +124,7 @@ public class MultiMeetServiceImpl implements MultiMeetService { ...@@ -122,6 +124,7 @@ public class MultiMeetServiceImpl implements MultiMeetService {
if (rtcRoomMember != null) { if (rtcRoomMember != null) {
// 该房间已邀请过一次,再次发起邀请 // 该房间已邀请过一次,再次发起邀请
rtcRoomMember.setState(MultiRtcMemberStateEnum.CALLING.getCode()); rtcRoomMember.setState(MultiRtcMemberStateEnum.CALLING.getCode());
rtcRoomMember.setCallTime(new Date());
imMultiRtcRoomMemberService.updateById(rtcRoomMember); imMultiRtcRoomMemberService.updateById(rtcRoomMember);
continue; continue;
} }
...@@ -132,6 +135,7 @@ public class MultiMeetServiceImpl implements MultiMeetService { ...@@ -132,6 +135,7 @@ public class MultiMeetServiceImpl implements MultiMeetService {
roomMember.setFkClientId(toClient.getId()); roomMember.setFkClientId(toClient.getId());
roomMember.setClientId(toClient.getClientId()); roomMember.setClientId(toClient.getClientId());
roomMember.setState(MultiRtcMemberStateEnum.CALLING.getCode()); roomMember.setState(MultiRtcMemberStateEnum.CALLING.getCode());
roomMember.setCallTime(new Date());
roomMember.setCreateTime(new Date()); roomMember.setCreateTime(new Date());
roomMember.setUpdateTime(new Date()); roomMember.setUpdateTime(new Date());
roomMembersToSave.add(roomMember); roomMembersToSave.add(roomMember);
...@@ -149,6 +153,8 @@ public class MultiMeetServiceImpl implements MultiMeetService { ...@@ -149,6 +153,8 @@ public class MultiMeetServiceImpl implements MultiMeetService {
roomMember.setFkClientId(currentClient.getId()); roomMember.setFkClientId(currentClient.getId());
roomMember.setClientId(currentClient.getClientId()); roomMember.setClientId(currentClient.getClientId());
roomMember.setState(MultiRtcMemberStateEnum.ANSWERED.getCode()); roomMember.setState(MultiRtcMemberStateEnum.ANSWERED.getCode());
roomMember.setCallTime(new Date());
roomMember.setHeartbeatTime(new Date());
roomMember.setCreateTime(new Date()); roomMember.setCreateTime(new Date());
roomMember.setUpdateTime(new Date()); roomMember.setUpdateTime(new Date());
roomMembersToSave.add(roomMember); roomMembersToSave.add(roomMember);
...@@ -266,13 +272,22 @@ public class MultiMeetServiceImpl implements MultiMeetService { ...@@ -266,13 +272,22 @@ public class MultiMeetServiceImpl implements MultiMeetService {
} }
@Override @Override
public void heartbeat(HeartbeatMultiMeetParam param) {
ImClient currentClient = imClientService.getCurrentClient();
imMultiRtcRoomMemberService.update(new UpdateWrapper<ImMultiRtcRoomMember>().lambda()
.eq(ImMultiRtcRoomMember::getRoomId, param.getRoomId())
.eq(ImMultiRtcRoomMember::getFkClientId, currentClient.getId())
.set(ImMultiRtcRoomMember::getHeartbeatTime, new Date()));
}
@Override
public void callingTimeout() { public void callingTimeout() {
// 10 秒之前的时间 // 60 秒之前的时间
Date tenSecondsBefore = DateUtils.addSeconds(new Date(), -10); Date beforeTime = DateUtils.addSeconds(new Date(), -60);
// 获取呼叫时间为10秒之前 并且状态为呼叫中的会议成员 // 获取呼叫时间为120秒之前 并且状态为呼叫中的会议成员
List<ImMultiRtcRoomMember> rtcRoomMemberList = imMultiRtcRoomMemberService.list( List<ImMultiRtcRoomMember> rtcRoomMemberList = imMultiRtcRoomMemberService.list(
new QueryWrapper<ImMultiRtcRoomMember>().lambda() new QueryWrapper<ImMultiRtcRoomMember>().lambda()
.eq(ImMultiRtcRoomMember::getCallTime, tenSecondsBefore) .lt(ImMultiRtcRoomMember::getCallTime, beforeTime)
.eq(ImMultiRtcRoomMember::getState, MultiRtcMemberStateEnum.CALLING.getCode()) .eq(ImMultiRtcRoomMember::getState, MultiRtcMemberStateEnum.CALLING.getCode())
); );
if (CollectionUtils.isEmpty(rtcRoomMemberList)) { if (CollectionUtils.isEmpty(rtcRoomMemberList)) {
...@@ -284,4 +299,23 @@ public class MultiMeetServiceImpl implements MultiMeetService { ...@@ -284,4 +299,23 @@ public class MultiMeetServiceImpl implements MultiMeetService {
imMultiRtcRoomMemberService.updateBatchById(rtcRoomMemberList); imMultiRtcRoomMemberService.updateBatchById(rtcRoomMemberList);
} }
@Override
public void disconnect() {
// 20 秒之前的时间
Date beforeTime = DateUtils.addSeconds(new Date(), -20);
// 获取最后心跳时间为20秒之前 并且状态为接听中的会议成员
List<ImMultiRtcRoomMember> rtcRoomMemberList = imMultiRtcRoomMemberService.list(
new QueryWrapper<ImMultiRtcRoomMember>().lambda()
.lt(ImMultiRtcRoomMember::getHeartbeatTime, beforeTime)
.eq(ImMultiRtcRoomMember::getState, MultiRtcMemberStateEnum.ANSWERED.getCode())
);
if (CollectionUtils.isEmpty(rtcRoomMemberList)) {
return;
}
for (ImMultiRtcRoomMember roomMember : rtcRoomMemberList) {
roomMember.setState(MultiRtcMemberStateEnum.DISCONNECT.getCode());
}
imMultiRtcRoomMemberService.updateBatchById(rtcRoomMemberList);
}
} }
-- 在feature-cluster 2021年12月22日之后,需要执行的的sql增量脚本 -- 在feature-cluster 2021年12月22日之后,需要执行的的sql增量脚本
...@@ -119,6 +119,7 @@ CREATE TABLE `im_client_device` ...@@ -119,6 +119,7 @@ CREATE TABLE `im_client_device`
-- 20220315 by wenzhida -- 20220315 by wenzhida
DROP TABLE IF EXISTS `im_multi_rtc_room`;
CREATE TABLE `im_multi_rtc_room` CREATE TABLE `im_multi_rtc_room`
( (
`id` bigint NOT NULL COMMENT '主键id', `id` bigint NOT NULL COMMENT '主键id',
...@@ -132,6 +133,7 @@ CREATE TABLE `im_multi_rtc_room` ...@@ -132,6 +133,7 @@ CREATE TABLE `im_multi_rtc_room`
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='多人音视频房间表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='多人音视频房间表';
DROP TABLE IF EXISTS `im_multi_rtc_room_member`;
CREATE TABLE `im_multi_rtc_room_member` CREATE TABLE `im_multi_rtc_room_member`
( (
`id` bigint NOT NULL COMMENT '主键id', `id` bigint NOT NULL COMMENT '主键id',
...@@ -141,12 +143,14 @@ CREATE TABLE `im_multi_rtc_room_member` ...@@ -141,12 +143,14 @@ CREATE TABLE `im_multi_rtc_room_member`
`client_id` varchar(200) DEFAULT NULL COMMENT '客户方提供的唯一id', `client_id` varchar(200) DEFAULT NULL COMMENT '客户方提供的唯一id',
`state` tinyint NOT NULL DEFAULT '1' COMMENT '房间成员状态,1:呼叫中,2:已接听,3:已拒绝,4:未接听,5:已断开', `state` tinyint NOT NULL DEFAULT '1' COMMENT '房间成员状态,1:呼叫中,2:已接听,3:已拒绝,4:未接听,5:已断开',
`call_time` timestamp NULL DEFAULT NULL COMMENT '呼叫时间', `call_time` timestamp NULL DEFAULT NULL COMMENT '呼叫时间',
`heartbeat_time` timestamp NULL DEFAULT NULL COMMENT '心跳时间',
`create_time` timestamp NULL DEFAULT NULL COMMENT '创建时间', `create_time` timestamp NULL DEFAULT NULL COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', `update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE, PRIMARY KEY (`id`) USING BTREE,
KEY `idx_fk_rtc_room_id` (`fk_rtc_room_id`) USING BTREE, KEY `idx_fk_rtc_room_id` (`fk_rtc_room_id`) USING BTREE,
KEY `idx_room_id` (`room_id`) USING BTREE, KEY `idx_room_id` (`room_id`) USING BTREE,
KEY `idx_call_time_state` (`call_time`, `state`) USING BTREE, KEY `idx_call_time_state` (`call_time`, `state`) USING BTREE,
KEY `idx_heartbeat_time_state` (`heartbeat_time`, `state`) USING BTREE,
KEY `idx_client_id` (`client_id`) USING BTREE KEY `idx_client_id` (`client_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='多人音视频房间成员表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='多人音视频房间成员表';
......
...@@ -29,4 +29,15 @@ public class MultiMeetScheduled { ...@@ -29,4 +29,15 @@ public class MultiMeetScheduled {
log.info("呼叫超时处理结束..."); log.info("呼叫超时处理结束...");
} }
/**
* 接听中成员异常断线处理
* 每10秒执行一次 (5秒一次心跳 - 20秒未收到心跳,认为已经异常断开连接)
*/
@Scheduled(cron = "*/10 * * * * ?")
public void disconnect() {
log.info("异常断线处理开始...");
multiMeetService.disconnect();
log.info("异常断线处理结束...");
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment