Commit ee01a16f8b358e4b7149822fd1bcb1fdbfc4d433
1 parent
eb2d3c39
🐛 fix(im):好友模块 codex 评审修复——1209 改 @TransactionalEventListener(AFTER_COMMIT) 避免幽灵…
…通知、Consumer 过滤下推 SQL、申请表索引带 id 后缀覆盖游标排序、limit 加 @Max(200) 上限
Showing
4 changed files
with
20 additions
and
13 deletions
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/friend/ImFriendRequestController.java
| ... | ... | @@ -16,6 +16,7 @@ import io.swagger.v3.oas.annotations.Parameter; |
| 16 | 16 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 17 | 17 | import jakarta.annotation.Resource; |
| 18 | 18 | import jakarta.validation.Valid; |
| 19 | +import jakarta.validation.constraints.Max; | |
| 19 | 20 | import jakarta.validation.constraints.Min; |
| 20 | 21 | import jakarta.validation.constraints.NotNull; |
| 21 | 22 | import jakarta.validation.constraints.Size; |
| ... | ... | @@ -81,7 +82,8 @@ public class ImFriendRequestController { |
| 81 | 82 | public CommonResult<List<ImFriendRequestRespVO>> getMyFriendRequestList( |
| 82 | 83 | @Parameter(description = "当前列表最旧记录的 id;首页不传") |
| 83 | 84 | @RequestParam(value = "lastRequestId", required = false) Long lastRequestId, |
| 84 | - @Parameter(description = "单次拉取条数", required = true) @RequestParam("limit") @Min(1) Integer limit) { | |
| 85 | + @Parameter(description = "单次拉取条数", required = true) | |
| 86 | + @RequestParam("limit") @Min(1) @Max(200) Integer limit) { | |
| 85 | 87 | List<ImFriendRequestDO> list = friendRequestService.getMyFriendRequestList(getLoginUserId(), lastRequestId, limit); |
| 86 | 88 | return success(buildList(list)); |
| 87 | 89 | } | ... | ... |
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/mq/consumer/friend/AdminUserProfileUpdateConsumer.java
| 1 | 1 | package cn.iocoder.yudao.module.im.mq.consumer.friend; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | |
| 4 | 3 | import cn.iocoder.yudao.module.im.dal.dataobject.friend.ImFriendDO; |
| 5 | 4 | import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; |
| 6 | 5 | import cn.iocoder.yudao.module.im.service.friend.ImFriendService; |
| ... | ... | @@ -10,9 +9,10 @@ import cn.iocoder.yudao.module.im.service.websocket.dto.notification.friend.Frie |
| 10 | 9 | import cn.iocoder.yudao.module.system.api.message.user.AdminUserProfileUpdateMessage; |
| 11 | 10 | import jakarta.annotation.Resource; |
| 12 | 11 | import lombok.extern.slf4j.Slf4j; |
| 13 | -import org.springframework.context.event.EventListener; | |
| 14 | 12 | import org.springframework.scheduling.annotation.Async; |
| 15 | 13 | import org.springframework.stereotype.Component; |
| 14 | +import org.springframework.transaction.event.TransactionPhase; | |
| 15 | +import org.springframework.transaction.event.TransactionalEventListener; | |
| 16 | 16 | |
| 17 | 17 | import java.util.List; |
| 18 | 18 | |
| ... | ... | @@ -30,30 +30,25 @@ public class AdminUserProfileUpdateConsumer { |
| 30 | 30 | @Resource |
| 31 | 31 | private ImWebSocketService websocketService; |
| 32 | 32 | |
| 33 | - @EventListener | |
| 34 | - @Async // Spring Event 默认在 Producer 发送的线程,通过 @Async 实现异步 | |
| 33 | + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true) | |
| 34 | + @Async // Spring Event 默认在 Producer 发送的线程,通过 @Async 实现异步;事务提交后触发,避免回滚误推幽灵通知 / Consumer 抢在 commit 前读旧值 | |
| 35 | 35 | public void onMessage(AdminUserProfileUpdateMessage message) { |
| 36 | 36 | log.info("[onMessage][消息内容({})]", message); |
| 37 | 37 | Long userId = message.getUserId(); |
| 38 | - // 1. 找当前用户的所有有效好友(DISABLE 已删的不推) | |
| 39 | - List<ImFriendDO> friends = friendService.getFriendList(userId); | |
| 38 | + // 1. SQL 层过滤 ENABLE 好友 | |
| 39 | + List<ImFriendDO> friends = friendService.getEnableFriendList(userId); | |
| 40 | 40 | if (friends.isEmpty()) { |
| 41 | 41 | return; |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | // 2. 给每个好友的多端推 FRIEND_INFO_UPDATED;payload 里 operatorUserId / friendUserId 都是「资料被改的人」 |
| 45 | - int notifyCount = 0; | |
| 46 | 45 | for (ImFriendDO friend : friends) { |
| 47 | - if (CommonStatusEnum.isDisable(friend.getStatus())) { | |
| 48 | - continue; | |
| 49 | - } | |
| 50 | 46 | FriendInfoUpdatedNotification payload = (FriendInfoUpdatedNotification) new FriendInfoUpdatedNotification() |
| 51 | 47 | .setOperatorUserId(userId).setFriendUserId(userId); |
| 52 | 48 | websocketService.sendPrivateMessageAsync(friend.getFriendUserId(), ImPrivateMessageDTO.ofFriendNotification( |
| 53 | 49 | ImMessageTypeEnum.FRIEND_INFO_UPDATED.getType(), userId, friend.getFriendUserId(), payload)); |
| 54 | - notifyCount++; | |
| 55 | 50 | } |
| 56 | - log.info("[onMessage][userId({}) 推送 FRIEND_INFO_UPDATED 给 {} 位好友]", userId, notifyCount); | |
| 51 | + log.info("[onMessage][userId({}) 推送 FRIEND_INFO_UPDATED 给 {} 位好友]", userId, friends.size()); | |
| 57 | 52 | } |
| 58 | 53 | |
| 59 | 54 | } | ... | ... |
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendService.java
| ... | ... | @@ -33,6 +33,11 @@ public interface ImFriendService { |
| 33 | 33 | List<ImFriendDO> getFriendList(Long userId); |
| 34 | 34 | |
| 35 | 35 | /** |
| 36 | + * 获得当前用户的有效好友列表(仅 ENABLE 状态) | |
| 37 | + */ | |
| 38 | + List<ImFriendDO> getEnableFriendList(Long userId); | |
| 39 | + | |
| 40 | + /** | |
| 36 | 41 | * 获得当前用户与指定用户之间的有效好友列表(仅 ENABLE 状态) |
| 37 | 42 | */ |
| 38 | 43 | List<ImFriendDO> getActiveFriendList(Long userId, Collection<Long> friendUserIds); | ... | ... |
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java
| ... | ... | @@ -76,6 +76,11 @@ public class ImFriendServiceImpl implements ImFriendService { |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | 78 | @Override |
| 79 | + public List<ImFriendDO> getEnableFriendList(Long userId) { | |
| 80 | + return friendMapper.selectListByUserIdAndStatus(userId, CommonStatusEnum.ENABLE.getStatus()); | |
| 81 | + } | |
| 82 | + | |
| 83 | + @Override | |
| 79 | 84 | public List<ImFriendDO> getActiveFriendList(Long userId, Collection<Long> friendUserIds) { |
| 80 | 85 | return friendMapper.selectListByUserIdAndFriendUserIdsAndStatus(userId, friendUserIds, |
| 81 | 86 | CommonStatusEnum.ENABLE.getStatus()); | ... | ... |