From bd277263011a18e93f773d88dfc388dc143c46e6 Mon Sep 17 00:00:00 2001 From: hy001 Date: Tue, 21 Apr 2026 20:06:50 +0800 Subject: [PATCH] fix(other): ignore closed rooms when resolving current room --- .../other-infrastructure/pom.xml | 18 +- .../impl/RoomProfileManagerServiceImpl.java | 227 +++++++++++------- .../RoomProfileManagerServiceImplTest.java | 104 ++++++++ 3 files changed, 253 insertions(+), 96 deletions(-) create mode 100644 rc-service/rc-service-other/other-infrastructure/src/test/java/com/red/circle/other/infra/database/mongo/service/live/impl/RoomProfileManagerServiceImplTest.java diff --git a/rc-service/rc-service-other/other-infrastructure/pom.xml b/rc-service/rc-service-other/other-infrastructure/pom.xml index ca213f8..487bd31 100644 --- a/rc-service/rc-service-other/other-infrastructure/pom.xml +++ b/rc-service/rc-service-other/other-infrastructure/pom.xml @@ -35,12 +35,18 @@ component-mongodb - - com.red.circle - business-rocketmq - - - + + com.red.circle + business-rocketmq + + + + org.springframework.boot + spring-boot-starter-test + test + + + rc-service-other diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/live/impl/RoomProfileManagerServiceImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/live/impl/RoomProfileManagerServiceImpl.java index 48df9fa..383dfdc 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/live/impl/RoomProfileManagerServiceImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/live/impl/RoomProfileManagerServiceImpl.java @@ -1,6 +1,5 @@ -package com.red.circle.other.infra.database.mongo.service.live.impl; - -import com.alibaba.fastjson.JSON; +package com.red.circle.other.infra.database.mongo.service.live.impl; + import com.google.common.collect.Lists; import com.mongodb.BasicDBObject; import com.red.circle.common.business.core.ReplaceString; @@ -23,12 +22,13 @@ import com.red.circle.tool.core.collection.CollectionUtils; import com.red.circle.tool.core.date.TimestampUtils; import com.red.circle.tool.core.obj.ObjectUtils; import com.red.circle.tool.core.text.StringUtils; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -107,11 +107,11 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService return ""; } - @Override - public boolean existsUserRoom(Long userId) { - return mongoTemplate.exists(Query.query(Criteria.where("userId").is(userId)), - RoomProfileManager.class); - } + @Override + public boolean existsUserRoom(Long userId) { + return mongoTemplate.exists(currentRoomQueryByUserId(userId), + RoomProfileManager.class); + } @Override public void create(RoomProfileManager profile) { @@ -127,12 +127,12 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService .orElse(null); } - @Override - public Long getRoomId(Long userId) { - Query query = Query.query(Criteria.where("userId").is(userId)); - query.fields().include("id"); - return Optional.ofNullable(mongoTemplate.findOne(query, RoomProfileManager.class)) - .map(RoomProfileManager::getId) + @Override + public Long getRoomId(Long userId) { + Query query = currentRoomQueryByUserId(userId); + query.fields().include("id"); + return Optional.ofNullable(mongoTemplate.findOne(query, RoomProfileManager.class)) + .map(RoomProfileManager::getId) .orElse(null); } @@ -153,12 +153,12 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService RoomProfileManager.class); } - @Override - public RoomProfile getProfileByUserId(Long userId) { - Query query = Query.query(Criteria.where("userId").is(userId)); - ObjectUtils.getObjectField(RoomProfile.class).forEach(field -> query.fields().include(field)); - return mongoTemplate.findOne(query, - RoomProfileManager.class); + @Override + public RoomProfile getProfileByUserId(Long userId) { + Query query = currentRoomQueryByUserId(userId); + ObjectUtils.getObjectField(RoomProfile.class).forEach(field -> query.fields().include(field)); + return mongoTemplate.findOne(query, + RoomProfileManager.class); } @Override @@ -168,12 +168,12 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService RoomProfileManager.class)); } - @Override - public RoomProfileManager getByUserId(Long userId) { - return filterExpireTimeDecorate( - mongoTemplate.findOne(Query.query(Criteria.where("userId").is(userId)), - RoomProfileManager.class)); - } + @Override + public RoomProfileManager getByUserId(Long userId) { + return filterExpireTimeDecorate( + mongoTemplate.findOne(currentRoomQueryByUserId(userId), + RoomProfileManager.class)); + } @Override public RoomProfileManager getByRoomAccount(String account) { @@ -247,18 +247,25 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService .orElseGet(Lists::newArrayList); } - @Override - public List listProfileByUserIds(Set userIds) { - System.out.println("id信息"+ JSON.toJSONString(userIds)); - if (CollectionUtils.isEmpty(userIds)) { - return Lists.newArrayList(); - } - Query query = Query.query(Criteria.where("userId").in(userIds)); - ObjectUtils.getObjectField(RoomProfile.class).forEach(field -> query.fields().include(field)); - return Optional.of(mongoTemplate.find(query, RoomProfileManager.class)) - .map(rooms -> rooms.stream().map(room -> (RoomProfile) room).collect(Collectors.toList())) - .orElseGet(Lists::newArrayList); - } + @Override + public List listProfileByUserIds(Set userIds) { + if (CollectionUtils.isEmpty(userIds)) { + return Lists.newArrayList(); + } + Query query = currentRoomQueryByUserIds(userIds); + ObjectUtils.getObjectField(RoomProfile.class).forEach(field -> query.fields().include(field)); + List rooms = mongoTemplate.find(query, RoomProfileManager.class); + if (CollectionUtils.isEmpty(rooms)) { + return Lists.newArrayList(); + } + Map latestRoomByUserId = new LinkedHashMap<>(); + rooms.forEach(room -> { + if (Objects.nonNull(room) && Objects.nonNull(room.getUserId())) { + latestRoomByUserId.putIfAbsent(room.getUserId(), room); + } + }); + return Lists.newArrayList(latestRoomByUserId.values()); + } @Override public List listSelectiveLimit100(String sysOrigin, String countryCode, @@ -358,12 +365,12 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService .orElse(null); } - @Override - public RoomSetting getRoomSettingByUserId(Long userId) { - Query query = Query.query(Criteria.where("userId").is(userId)); - query.fields().include("setting"); - return Optional.ofNullable(mongoTemplate.findOne(query, - RoomProfileManager.class)) + @Override + public RoomSetting getRoomSettingByUserId(Long userId) { + Query query = currentRoomQueryByUserId(userId); + query.fields().include("setting"); + return Optional.ofNullable(mongoTemplate.findOne(query, + RoomProfileManager.class)) .map(RoomProfileManager::getSetting) .orElse(null); } @@ -378,12 +385,12 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService .orElse(null); } - @Override - public RoomCounter getRoomCounterByUserId(Long userId) { - Query query = Query.query(Criteria.where("userId").is(userId)); - query.fields().include("counter"); - return Optional.ofNullable(mongoTemplate.findOne(query, - RoomProfileManager.class)) + @Override + public RoomCounter getRoomCounterByUserId(Long userId) { + Query query = currentRoomQueryByUserId(userId); + query.fields().include("counter"); + return Optional.ofNullable(mongoTemplate.findOne(query, + RoomProfileManager.class)) .map(RoomProfileManager::getCounter) .orElse(null); } @@ -471,12 +478,16 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService RoomProfileManager.class); } - @Override - public void updateSelectiveSettingByUserId(Long userId, RoomSetting roomSetting) { - mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)), - getUpdateSelectiveSetting(getRoomSettingByUserId(userId), roomSetting), - RoomProfileManager.class); - } + @Override + public void updateSelectiveSettingByUserId(Long userId, RoomSetting roomSetting) { + Long roomId = getRoomId(userId); + if (Objects.isNull(roomId)) { + return; + } + mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)), + getUpdateSelectiveSetting(getRoomSettingById(roomId), roomSetting), + RoomProfileManager.class); + } @Override public void updatePassword(Long roomId, String password) { @@ -486,12 +497,16 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService RoomProfileManager.class); } - @Override - public void updateRoomCoverByUserId(Long userId, String cover) { - mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)), - new Update().set("updateTime", TimestampUtils.now()) - .set("roomCover", cover), - RoomProfileManager.class); + @Override + public void updateRoomCoverByUserId(Long userId, String cover) { + Long roomId = getRoomId(userId); + if (Objects.isNull(roomId)) { + return; + } + mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)), + new Update().set("updateTime", TimestampUtils.now()) + .set("roomCover", cover), + RoomProfileManager.class); } @Override @@ -526,21 +541,29 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService RoomProfileManager.class); } - @Override - public void updateUserCountry(Long userId, String countryCode, String countryName) { - mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)), - new Update().set("updateTime", TimestampUtils.now()) - .set("countryCode", countryCode) - .set("countryName", countryName), + @Override + public void updateUserCountry(Long userId, String countryCode, String countryName) { + Long roomId = getRoomId(userId); + if (Objects.isNull(roomId)) { + return; + } + mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)), + new Update().set("updateTime", TimestampUtils.now()) + .set("countryCode", countryCode) + .set("countryName", countryName), RoomProfileManager.class); } - @Override - public void updateUserLangCode(Long userId, String langCode) { - mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)), - new Update().set("updateTime", TimestampUtils.now()) - .set("langCode", StringUtils.toUpperCase(langCode)), - RoomProfileManager.class); + @Override + public void updateUserLangCode(Long userId, String langCode) { + Long roomId = getRoomId(userId); + if (Objects.isNull(roomId)) { + return; + } + mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)), + new Update().set("updateTime", TimestampUtils.now()) + .set("langCode", StringUtils.toUpperCase(langCode)), + RoomProfileManager.class); } @Override @@ -591,16 +614,40 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService RoomProfileManager.class); } - @Override - public void delUserRoom(Long userId) { - mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)), - new Update().set("updateTime", TimestampUtils.now()) - .set("del", Boolean.TRUE), - RoomProfileManager.class); - } - - private List filterPropsNotAvailable(List useProps) { - if (CollectionUtils.isNotEmpty(useProps)) { + @Override + public void delUserRoom(Long userId) { + mongoTemplate.updateMulti(currentRoomQueryByUserId(userId), + new Update().set("updateTime", TimestampUtils.now()) + .set("del", Boolean.TRUE), + RoomProfileManager.class); + } + + private Query currentRoomQueryByUserId(Long userId) { + return Query.query(currentRoomCriteria().and("userId").is(userId)) + .with(Sort.by( + Sort.Order.desc("updateTime"), + Sort.Order.desc("createTime"), + Sort.Order.desc("id") + )); + } + + private Query currentRoomQueryByUserIds(Set userIds) { + return Query.query(currentRoomCriteria().and("userId").in(userIds)) + .with(Sort.by( + Sort.Order.asc("userId"), + Sort.Order.desc("updateTime"), + Sort.Order.desc("createTime"), + Sort.Order.desc("id") + )); + } + + private Criteria currentRoomCriteria() { + return Criteria.where("del").ne(Boolean.TRUE) + .and("event").ne(RoomEventEnum.CLOSE.name()); + } + + private List filterPropsNotAvailable(List useProps) { + if (CollectionUtils.isNotEmpty(useProps)) { return useProps.stream().filter(badge -> checkAvailable(badge.getExpireTime())) .collect(Collectors.toList()); } diff --git a/rc-service/rc-service-other/other-infrastructure/src/test/java/com/red/circle/other/infra/database/mongo/service/live/impl/RoomProfileManagerServiceImplTest.java b/rc-service/rc-service-other/other-infrastructure/src/test/java/com/red/circle/other/infra/database/mongo/service/live/impl/RoomProfileManagerServiceImplTest.java new file mode 100644 index 0000000..cf03752 --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/test/java/com/red/circle/other/infra/database/mongo/service/live/impl/RoomProfileManagerServiceImplTest.java @@ -0,0 +1,104 @@ +package com.red.circle.other.infra.database.mongo.service.live.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.red.circle.other.infra.common.sys.CountryCodeAliasSupport; +import com.red.circle.other.infra.database.cache.service.other.RoomManagerCacheService; +import com.red.circle.other.infra.database.mongo.entity.live.RoomProfile; +import com.red.circle.other.infra.database.mongo.entity.live.RoomProfileManager; +import com.red.circle.other.infra.database.mongo.service.live.ActiveVoiceRoomService; +import java.util.List; +import java.util.Set; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.bson.Document; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.redis.core.RedisTemplate; + +class RoomProfileManagerServiceImplTest { + + private MongoTemplate mongoTemplate; + private RoomProfileManagerServiceImpl service; + + @BeforeEach + void setUp() { + mongoTemplate = mock(MongoTemplate.class); + RedisTemplate redisTemplate = mock(RedisTemplate.class); + ActiveVoiceRoomService activeVoiceRoomService = mock(ActiveVoiceRoomService.class); + RoomManagerCacheService roomManagerCacheService = mock(RoomManagerCacheService.class); + CountryCodeAliasSupport countryCodeAliasSupport = mock(CountryCodeAliasSupport.class); + service = new RoomProfileManagerServiceImpl( + mongoTemplate, + redisTemplate, + activeVoiceRoomService, + roomManagerCacheService, + countryCodeAliasSupport + ); + } + + @Test + void existsUserRoom_shouldIgnoreClosedOrDeletedHistoryRooms() { + ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); + when(mongoTemplate.exists(queryCaptor.capture(), eq(RoomProfileManager.class))).thenReturn(false); + + boolean exists = service.existsUserRoom(123456L); + + assertFalse(exists); + Document queryObject = queryCaptor.getValue().getQueryObject(); + Document sortObject = queryCaptor.getValue().getSortObject(); + assertEquals(123456L, queryObject.getLong("userId")); + assertEquals(Boolean.TRUE, ((Document) queryObject.get("del")).getBoolean("$ne")); + assertEquals("CLOSE", ((Document) queryObject.get("event")).getString("$ne")); + assertEquals(-1, sortObject.getInteger("updateTime")); + assertEquals(-1, sortObject.getInteger("createTime")); + assertEquals(-1, sortObject.getInteger("id")); + } + + @Test + void listProfileByUserIds_shouldKeepLatestCurrentRoomPerUser() { + RoomProfileManager latestRoom = new RoomProfileManager(); + latestRoom.setId(11L); + latestRoom.setUserId(1L); + + RoomProfileManager oldRoom = new RoomProfileManager(); + oldRoom.setId(10L); + oldRoom.setUserId(1L); + + RoomProfileManager anotherUserRoom = new RoomProfileManager(); + anotherUserRoom.setId(21L); + anotherUserRoom.setUserId(2L); + + when(mongoTemplate.find(any(Query.class), eq(RoomProfileManager.class))).thenReturn( + List.of(latestRoom, oldRoom, anotherUserRoom) + ); + + List profiles = service.listProfileByUserIds(Set.of(1L, 2L)); + + assertEquals(2, profiles.size()); + assertSame(latestRoom, profiles.get(0)); + assertSame(anotherUserRoom, profiles.get(1)); + } + + @Test + void updateRoomCoverByUserId_shouldUpdateResolvedCurrentRoom() { + RoomProfileManager room = new RoomProfileManager(); + room.setId(99L); + + when(mongoTemplate.findOne(any(Query.class), eq(RoomProfileManager.class))).thenReturn(room); + + service.updateRoomCoverByUserId(123456L, "cover.png"); + + ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); + verify(mongoTemplate).updateFirst(queryCaptor.capture(), any(), eq(RoomProfileManager.class)); + assertEquals(99L, queryCaptor.getValue().getQueryObject().getLong("id")); + } +}