|
|
@ -10,7 +10,6 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|
|
import com.bx.imclient.IMClient; |
|
|
import com.bx.imclient.IMClient; |
|
|
import com.bx.imcommon.contant.IMConstant; |
|
|
import com.bx.imcommon.contant.IMConstant; |
|
|
import com.bx.imcommon.enums.IMTerminalType; |
|
|
|
|
|
import com.bx.imcommon.model.IMGroupMessage; |
|
|
import com.bx.imcommon.model.IMGroupMessage; |
|
|
import com.bx.imcommon.model.IMUserInfo; |
|
|
import com.bx.imcommon.model.IMUserInfo; |
|
|
import com.bx.imcommon.util.CommaTextUtils; |
|
|
import com.bx.imcommon.util.CommaTextUtils; |
|
|
@ -143,115 +142,6 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro |
|
|
return msgInfo; |
|
|
return msgInfo; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
public void pullOfflineMessage(Long minId) { |
|
|
|
|
|
UserSession session = SessionContext.getSession(); |
|
|
|
|
|
if (!imClient.isOnline(session.getUserId())) { |
|
|
|
|
|
throw new GlobalException("网络连接失败,无法拉取离线消息"); |
|
|
|
|
|
} |
|
|
|
|
|
// 查询用户加入的群组
|
|
|
|
|
|
List<GroupMember> members = groupMemberService.findByUserId(session.getUserId()); |
|
|
|
|
|
Map<Long, GroupMember> groupMemberMap = CollStreamUtil.toIdentityMap(members, GroupMember::getGroupId); |
|
|
|
|
|
Set<Long> groupIds = groupMemberMap.keySet(); |
|
|
|
|
|
if (CollectionUtil.isEmpty(groupIds)) { |
|
|
|
|
|
// 关闭加载中标志
|
|
|
|
|
|
this.sendLoadingMessage(false, session); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
// 只拉最近一个月
|
|
|
|
|
|
Date minDate = DateUtils.addMonths(new Date(), -1); |
|
|
|
|
|
LambdaQueryWrapper<GroupMessage> wrapper = Wrappers.lambdaQuery(); |
|
|
|
|
|
wrapper.gt(GroupMessage::getId, minId); |
|
|
|
|
|
wrapper.gt(GroupMessage::getSendTime, minDate); |
|
|
|
|
|
wrapper.in(GroupMessage::getGroupId, groupIds); |
|
|
|
|
|
wrapper.orderByDesc(GroupMessage::getId); |
|
|
|
|
|
wrapper.last("limit 50000"); |
|
|
|
|
|
List<GroupMessage> messages = this.list(wrapper); |
|
|
|
|
|
// 通过群聊对消息进行分组
|
|
|
|
|
|
Map<Long, List<GroupMessage>> messageGroupMap = |
|
|
|
|
|
messages.stream().collect(Collectors.groupingBy(GroupMessage::getGroupId)); |
|
|
|
|
|
// 退群前的消息
|
|
|
|
|
|
List<GroupMember> quitMembers = groupMemberService.findQuitInMonth(session.getUserId()); |
|
|
|
|
|
for (GroupMember quitMember : quitMembers) { |
|
|
|
|
|
wrapper = Wrappers.lambdaQuery(); |
|
|
|
|
|
wrapper.gt(GroupMessage::getId, minId); |
|
|
|
|
|
wrapper.between(GroupMessage::getSendTime, minDate, quitMember.getQuitTime()); |
|
|
|
|
|
wrapper.eq(GroupMessage::getGroupId, quitMember.getGroupId()); |
|
|
|
|
|
wrapper.ne(GroupMessage::getStatus, MessageStatus.RECALL.code()); |
|
|
|
|
|
wrapper.orderByDesc(GroupMessage::getId); |
|
|
|
|
|
List<GroupMessage> groupMessages = this.list(wrapper); |
|
|
|
|
|
messageGroupMap.put(quitMember.getGroupId(), groupMessages); |
|
|
|
|
|
groupMemberMap.put(quitMember.getGroupId(), quitMember); |
|
|
|
|
|
} |
|
|
|
|
|
EXECUTOR.execute(() -> { |
|
|
|
|
|
// 开启加载中标志
|
|
|
|
|
|
this.sendLoadingMessage(true, session); |
|
|
|
|
|
// 推送消息
|
|
|
|
|
|
int sendCount = 0; |
|
|
|
|
|
for (Map.Entry<Long, List<GroupMessage>> entry : messageGroupMap.entrySet()) { |
|
|
|
|
|
Long groupId = entry.getKey(); |
|
|
|
|
|
List<GroupMessage> groupMessages = entry.getValue(); |
|
|
|
|
|
// 第一次拉取时,一个群最多推送3000条消息,防止前端接收能力溢出导致卡顿
|
|
|
|
|
|
List<GroupMessage> sendMessages = groupMessages; |
|
|
|
|
|
if (minId <= 0 && groupMessages.size() > 3000) { |
|
|
|
|
|
sendMessages = groupMessages.subList(0, 3000); |
|
|
|
|
|
} |
|
|
|
|
|
// id从小到大排序
|
|
|
|
|
|
CollectionUtil.reverse(sendMessages); |
|
|
|
|
|
// 填充消息状态
|
|
|
|
|
|
String key = StrUtil.join(":", RedisKey.IM_GROUP_READED_POSITION, groupId); |
|
|
|
|
|
Object o = redisTemplate.opsForHash().get(key, session.getUserId().toString()); |
|
|
|
|
|
long readedMaxId = Objects.isNull(o) ? -1 : Long.parseLong(o.toString()); |
|
|
|
|
|
Map<Object, Object> maxIdMap = null; |
|
|
|
|
|
for (GroupMessage m : sendMessages) { |
|
|
|
|
|
// 推送过程如果用户下线了,则不再推送
|
|
|
|
|
|
if (!imClient.isOnline(session.getUserId(), IMTerminalType.fromCode(session.getTerminal()))) { |
|
|
|
|
|
log.info("用户已下线,停止推送离线群聊消息,用户id:{}", session.getUserId()); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
// 排除加群之前的消息
|
|
|
|
|
|
GroupMember member = groupMemberMap.get(m.getGroupId()); |
|
|
|
|
|
if (DateUtil.compare(member.getCreatedTime(), m.getSendTime()) > 0) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
// 排除不需要接收的消息
|
|
|
|
|
|
List<String> recvIds = CommaTextUtils.asList(m.getRecvIds()); |
|
|
|
|
|
if (!recvIds.isEmpty() && !recvIds.contains(session.getUserId().toString())) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
// 组装vo
|
|
|
|
|
|
GroupMessageVO vo = BeanUtils.copyProperties(m, GroupMessageVO.class); |
|
|
|
|
|
// 被@用户列表
|
|
|
|
|
|
List<String> atIds = CommaTextUtils.asList(m.getAtUserIds()); |
|
|
|
|
|
vo.setAtUserIds(atIds.stream().map(Long::parseLong).collect(Collectors.toList())); |
|
|
|
|
|
// 填充状态
|
|
|
|
|
|
vo.setStatus(readedMaxId >= m.getId() ? MessageStatus.READED.code() : MessageStatus.PENDING.code()); |
|
|
|
|
|
// 针对回执消息填充已读人数
|
|
|
|
|
|
if (m.getReceipt()) { |
|
|
|
|
|
if (Objects.isNull(maxIdMap)) { |
|
|
|
|
|
maxIdMap = redisTemplate.opsForHash().entries(key); |
|
|
|
|
|
} |
|
|
|
|
|
int count = getReadedUserIds(maxIdMap, m.getId(), m.getSendId()).size(); |
|
|
|
|
|
vo.setReadedCount(count); |
|
|
|
|
|
} |
|
|
|
|
|
// 推送
|
|
|
|
|
|
IMGroupMessage<GroupMessageVO> sendMessage = new IMGroupMessage<>(); |
|
|
|
|
|
sendMessage.setSender(new IMUserInfo(m.getSendId(), IMTerminalType.WEB.code())); |
|
|
|
|
|
sendMessage.setRecvIds(Arrays.asList(session.getUserId())); |
|
|
|
|
|
sendMessage.setRecvTerminals(Arrays.asList(session.getTerminal())); |
|
|
|
|
|
sendMessage.setSendResult(false); |
|
|
|
|
|
sendMessage.setSendToSelf(false); |
|
|
|
|
|
sendMessage.setData(vo); |
|
|
|
|
|
imClient.sendGroupMessage(sendMessage); |
|
|
|
|
|
sendCount++; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
// 关闭加载中标志
|
|
|
|
|
|
this.sendLoadingMessage(false, session); |
|
|
|
|
|
log.info("拉取离线群聊消息,用户id:{},数量:{}", session.getUserId(), sendCount++); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public List<GroupMessageVO> loadOffineMessage(Long minId) { |
|
|
public List<GroupMessageVO> loadOffineMessage(Long minId) { |
|
|
UserSession session = SessionContext.getSession(); |
|
|
UserSession session = SessionContext.getSession(); |
|
|
@ -262,8 +152,8 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro |
|
|
if (groupIds.isEmpty()) { |
|
|
if (groupIds.isEmpty()) { |
|
|
return Collections.EMPTY_LIST; |
|
|
return Collections.EMPTY_LIST; |
|
|
} |
|
|
} |
|
|
// 只能拉取最近1个月的消息
|
|
|
// 只能拉取最近30天的消息
|
|
|
Date minDate = DateUtils.addMonths(new Date(), -1); |
|
|
Date minDate = DateUtils.addDays(new Date(), Math.toIntExact(-Constant.MAX_OFFLINE_MESSAGE_DAYS)); |
|
|
LambdaQueryWrapper<GroupMessage> wrapper = Wrappers.lambdaQuery(); |
|
|
LambdaQueryWrapper<GroupMessage> wrapper = Wrappers.lambdaQuery(); |
|
|
wrapper.gt(GroupMessage::getId, minId); |
|
|
wrapper.gt(GroupMessage::getId, minId); |
|
|
wrapper.gt(GroupMessage::getSendTime, minDate); |
|
|
wrapper.gt(GroupMessage::getSendTime, minDate); |
|
|
@ -271,8 +161,16 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro |
|
|
wrapper.orderByDesc(GroupMessage::getId); |
|
|
wrapper.orderByDesc(GroupMessage::getId); |
|
|
wrapper.last("limit 50000"); |
|
|
wrapper.last("limit 50000"); |
|
|
List<GroupMessage> messages = this.list(wrapper); |
|
|
List<GroupMessage> messages = this.list(wrapper); |
|
|
// 退群前的消息
|
|
|
// 查询退群前的消息
|
|
|
List<GroupMember> quitMembers = groupMemberService.findQuitInMonth(session.getUserId()); |
|
|
Date minQuitTime = minDate; |
|
|
|
|
|
if (minId > 0) { |
|
|
|
|
|
// 如果某个群的退群时间大于起始消息的发送时间,那消息是不用推送的,过滤掉
|
|
|
|
|
|
GroupMessage message = this.getById(minId); |
|
|
|
|
|
if (!Objects.isNull(message) && message.getSendTime().compareTo(minDate) > 0) { |
|
|
|
|
|
minQuitTime = message.getSendTime(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
List<GroupMember> quitMembers = groupMemberService.findQuitMembers(session.getUserId(), minQuitTime); |
|
|
for (GroupMember quitMember : quitMembers) { |
|
|
for (GroupMember quitMember : quitMembers) { |
|
|
wrapper = Wrappers.lambdaQuery(); |
|
|
wrapper = Wrappers.lambdaQuery(); |
|
|
wrapper.gt(GroupMessage::getId, minId); |
|
|
wrapper.gt(GroupMessage::getId, minId); |
|
|
|