Commit dc7be585063ca833ff3b6fb07b68fde2ecc0146b

Authored by YunaiV
1 parent d6d90b2b

✨ feat(im): 优化 pullPrivateMessageList 接口的实现

yudao-module-im/yudao-module-im-biz/pom.xml
... ... @@ -23,6 +23,11 @@
23 23 <artifactId>yudao-module-im-api</artifactId>
24 24 <version>${revision}</version>
25 25 </dependency>
  26 + <dependency>
  27 + <groupId>cn.iocoder.boot</groupId>
  28 + <artifactId>yudao-module-system</artifactId>
  29 + <version>${revision}</version>
  30 + </dependency>
26 31  
27 32 <!-- Web 相关 -->
28 33 <dependency>
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/message/ImPrivateMessageController.java
... ... @@ -43,9 +43,9 @@ public class ImPrivateMessageController {
43 43 @Operation(summary = "拉取私聊消息(增量)")
44 44 @Parameter(name = "minId", description = "最小消息 id", required = true, example = "0")
45 45 @Parameter(name = "size", description = "拉取数量", required = true, example = "100")
46   - public CommonResult<List<ImPrivateMessageRespVO>> pullPrivateMessages(@RequestParam("minId") Long minId,
47   - @RequestParam("size") Integer size) {
48   - List<ImPrivateMessageDO> messages = privateMessageService.pullPrivateMessages(getLoginUserId(), minId, size);
  46 + public CommonResult<List<ImPrivateMessageRespVO>> pullPrivateMessageList(@RequestParam("minId") Long minId,
  47 + @RequestParam("size") Integer size) {
  48 + List<ImPrivateMessageDO> messages = privateMessageService.pullPrivateMessageList(getLoginUserId(), minId, size);
49 49 return success(BeanUtils.toBean(messages, ImPrivateMessageRespVO.class));
50 50 }
51 51  
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/message/ImPrivateMessageMapper.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.im.dal.mysql.message;
2 2  
3 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 4 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
5 6 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO;
6 7 import org.apache.ibatis.annotations.Mapper;
7 8  
... ... @@ -24,18 +25,15 @@ public interface ImPrivateMessageMapper extends BaseMapperX&lt;ImPrivateMessageDO&gt;
24 25 * @return 消息列表
25 26 */
26 27 default List<ImPrivateMessageDO> selectListByMinId(Long userId, Long minId, Integer size) {
27   - return selectList(new LambdaQueryWrapperX<ImPrivateMessageDO>()
28   - .and(w -> w.eq(ImPrivateMessageDO::getSenderId, userId)
29   - .or()
30   - .eq(ImPrivateMessageDO::getReceiverId, userId))
31   - .gt(ImPrivateMessageDO::getId, minId)
32   - .orderByAsc(ImPrivateMessageDO::getId)
33   - .last("LIMIT " + size));
  28 + QueryWrapperX<ImPrivateMessageDO> wrapper = new QueryWrapperX<>();
  29 + wrapper.and(w -> w.eq("sender_id", userId)
  30 + .or().eq("receiver_id", userId))
  31 + .gt("id", minId)
  32 + .orderByAsc("id");
  33 + wrapper.limitN(size);
  34 + return selectList(wrapper);
34 35 }
35 36  
36   - /**
37   - * 根据 senderId 和 clientMessageId 查询(幂等校验)
38   - */
39 37 default ImPrivateMessageDO selectBySenderIdAndClientMessageId(Long senderId, String clientMessageId) {
40 38 return selectOne(new LambdaQueryWrapperX<ImPrivateMessageDO>()
41 39 .eq(ImPrivateMessageDO::getSenderId, senderId)
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageService.java
... ... @@ -29,7 +29,7 @@ public interface ImPrivateMessageService {
29 29 * @param size 拉取数量
30 30 * @return 消息列表
31 31 */
32   - List<ImPrivateMessageDO> pullPrivateMessages(Long userId, Long minId, Integer size);
  32 + List<ImPrivateMessageDO> pullPrivateMessageList(Long userId, Long minId, Integer size);
33 33  
34 34 /**
35 35 * 标记私聊消息已读
... ...
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java
... ... @@ -81,29 +81,36 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
81 81 }
82 82  
83 83 @Override
84   - public List<ImPrivateMessageDO> pullPrivateMessages(Long userId, Long minId, Integer size) {
  84 + public List<ImPrivateMessageDO> pullPrivateMessageList(Long userId, Long minId, Integer size) {
85 85 if (size > MAX_PULL_SIZE) {
86 86 throw exception(MESSAGE_PULL_SIZE_EXCEEDED);
87 87 }
88   - return privateMessageMapper.selectListByMinId(userId, minId, size);
  88 + List<ImPrivateMessageDO> messages = privateMessageMapper.selectListByMinId(userId, minId, size);
  89 + log.info("[pullPrivateMessageList][userId({}) minId({}) size({}) result({})]",
  90 + userId, minId, size, messages.size());
  91 + return messages;
89 92 }
90 93  
91   - // DONE @芋艿:已 review,逻辑正确
  94 + // TODO @AI:应该是将 friendId 改成 receiverId,毕竟消息是发给对方的
92 95 @Override
93 96 public void readPrivateMessages(Long userId, Long friendId) {
94 97 // 1. 批量更新消息状态为已读
  98 + // TODO @AI:先查询;然后在 update;避免锁的问题;
  99 + // TODO @AI:注意,update 的时候,也要 id in、status =,最后 updateObj 传入;避免并发问题;
95 100 int updated = privateMessageMapper.updateStatusToRead(userId, friendId);
96 101 if (updated == 0) {
97 102 return; // 没有需要更新的消息
98 103 }
99   - // 2. 发送 READ 事件给自己的其他终端(多端同步)
  104 +
  105 + // TODO @AI:继续 async !
  106 + // 2.1 发送 READ 事件给自己的其他终端(多端同步)
100 107 ImMessageReadMessage readMessage = new ImMessageReadMessage()
101 108 .setFriendId(friendId.toString())
102 109 .setMessageScene("private");
103 110 webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), userId,
104 111 ImMessageReadMessage.TYPE, readMessage);
105 112  
106   - // 3. 发送 RECEIPT 事件给对方(已读回执)
  113 + // 2.2 发送 RECEIPT 事件给对方(已读回执)
107 114 ImMessageReceiptMessage receiptMessage = new ImMessageReceiptMessage()
108 115 .setUserId(userId.toString())
109 116 .setMessageScene("private");
... ...