fix(other): ignore closed rooms when resolving current room

This commit is contained in:
hy001 2026-04-21 20:06:50 +08:00
parent 9f06c67bf1
commit bd27726301
3 changed files with 253 additions and 96 deletions

View File

@ -35,12 +35,18 @@
<artifactId>component-mongodb</artifactId> <artifactId>component-mongodb</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.red.circle</groupId> <groupId>com.red.circle</groupId>
<artifactId>business-rocketmq</artifactId> <artifactId>business-rocketmq</artifactId>
</dependency> </dependency>
</dependencies> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<parent> <parent>
<artifactId>rc-service-other</artifactId> <artifactId>rc-service-other</artifactId>

View File

@ -1,6 +1,5 @@
package com.red.circle.other.infra.database.mongo.service.live.impl; package com.red.circle.other.infra.database.mongo.service.live.impl;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.mongodb.BasicDBObject; import com.mongodb.BasicDBObject;
import com.red.circle.common.business.core.ReplaceString; 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.date.TimestampUtils;
import com.red.circle.tool.core.obj.ObjectUtils; import com.red.circle.tool.core.obj.ObjectUtils;
import com.red.circle.tool.core.text.StringUtils; import com.red.circle.tool.core.text.StringUtils;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.LinkedHashMap;
import java.util.Map; import java.util.List;
import java.util.Objects; import java.util.Map;
import java.util.Optional; import java.util.Objects;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -107,11 +107,11 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
return ""; return "";
} }
@Override @Override
public boolean existsUserRoom(Long userId) { public boolean existsUserRoom(Long userId) {
return mongoTemplate.exists(Query.query(Criteria.where("userId").is(userId)), return mongoTemplate.exists(currentRoomQueryByUserId(userId),
RoomProfileManager.class); RoomProfileManager.class);
} }
@Override @Override
public void create(RoomProfileManager profile) { public void create(RoomProfileManager profile) {
@ -127,12 +127,12 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
.orElse(null); .orElse(null);
} }
@Override @Override
public Long getRoomId(Long userId) { public Long getRoomId(Long userId) {
Query query = Query.query(Criteria.where("userId").is(userId)); Query query = currentRoomQueryByUserId(userId);
query.fields().include("id"); query.fields().include("id");
return Optional.ofNullable(mongoTemplate.findOne(query, RoomProfileManager.class)) return Optional.ofNullable(mongoTemplate.findOne(query, RoomProfileManager.class))
.map(RoomProfileManager::getId) .map(RoomProfileManager::getId)
.orElse(null); .orElse(null);
} }
@ -153,12 +153,12 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
RoomProfileManager.class); RoomProfileManager.class);
} }
@Override @Override
public RoomProfile getProfileByUserId(Long userId) { public RoomProfile getProfileByUserId(Long userId) {
Query query = Query.query(Criteria.where("userId").is(userId)); Query query = currentRoomQueryByUserId(userId);
ObjectUtils.getObjectField(RoomProfile.class).forEach(field -> query.fields().include(field)); ObjectUtils.getObjectField(RoomProfile.class).forEach(field -> query.fields().include(field));
return mongoTemplate.findOne(query, return mongoTemplate.findOne(query,
RoomProfileManager.class); RoomProfileManager.class);
} }
@Override @Override
@ -168,12 +168,12 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
RoomProfileManager.class)); RoomProfileManager.class));
} }
@Override @Override
public RoomProfileManager getByUserId(Long userId) { public RoomProfileManager getByUserId(Long userId) {
return filterExpireTimeDecorate( return filterExpireTimeDecorate(
mongoTemplate.findOne(Query.query(Criteria.where("userId").is(userId)), mongoTemplate.findOne(currentRoomQueryByUserId(userId),
RoomProfileManager.class)); RoomProfileManager.class));
} }
@Override @Override
public RoomProfileManager getByRoomAccount(String account) { public RoomProfileManager getByRoomAccount(String account) {
@ -247,18 +247,25 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
.orElseGet(Lists::newArrayList); .orElseGet(Lists::newArrayList);
} }
@Override @Override
public List<RoomProfile> listProfileByUserIds(Set<Long> userIds) { public List<RoomProfile> listProfileByUserIds(Set<Long> userIds) {
System.out.println("id信息"+ JSON.toJSONString(userIds)); if (CollectionUtils.isEmpty(userIds)) {
if (CollectionUtils.isEmpty(userIds)) { return Lists.newArrayList();
return Lists.newArrayList(); }
} Query query = currentRoomQueryByUserIds(userIds);
Query query = Query.query(Criteria.where("userId").in(userIds)); ObjectUtils.getObjectField(RoomProfile.class).forEach(field -> query.fields().include(field));
ObjectUtils.getObjectField(RoomProfile.class).forEach(field -> query.fields().include(field)); List<RoomProfileManager> rooms = mongoTemplate.find(query, RoomProfileManager.class);
return Optional.of(mongoTemplate.find(query, RoomProfileManager.class)) if (CollectionUtils.isEmpty(rooms)) {
.map(rooms -> rooms.stream().map(room -> (RoomProfile) room).collect(Collectors.toList())) return Lists.newArrayList();
.orElseGet(Lists::newArrayList); }
} Map<Long, RoomProfile> 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 @Override
public List<RoomProfileManager> listSelectiveLimit100(String sysOrigin, String countryCode, public List<RoomProfileManager> listSelectiveLimit100(String sysOrigin, String countryCode,
@ -358,12 +365,12 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
.orElse(null); .orElse(null);
} }
@Override @Override
public RoomSetting getRoomSettingByUserId(Long userId) { public RoomSetting getRoomSettingByUserId(Long userId) {
Query query = Query.query(Criteria.where("userId").is(userId)); Query query = currentRoomQueryByUserId(userId);
query.fields().include("setting"); query.fields().include("setting");
return Optional.ofNullable(mongoTemplate.findOne(query, return Optional.ofNullable(mongoTemplate.findOne(query,
RoomProfileManager.class)) RoomProfileManager.class))
.map(RoomProfileManager::getSetting) .map(RoomProfileManager::getSetting)
.orElse(null); .orElse(null);
} }
@ -378,12 +385,12 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
.orElse(null); .orElse(null);
} }
@Override @Override
public RoomCounter getRoomCounterByUserId(Long userId) { public RoomCounter getRoomCounterByUserId(Long userId) {
Query query = Query.query(Criteria.where("userId").is(userId)); Query query = currentRoomQueryByUserId(userId);
query.fields().include("counter"); query.fields().include("counter");
return Optional.ofNullable(mongoTemplate.findOne(query, return Optional.ofNullable(mongoTemplate.findOne(query,
RoomProfileManager.class)) RoomProfileManager.class))
.map(RoomProfileManager::getCounter) .map(RoomProfileManager::getCounter)
.orElse(null); .orElse(null);
} }
@ -471,12 +478,16 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
RoomProfileManager.class); RoomProfileManager.class);
} }
@Override @Override
public void updateSelectiveSettingByUserId(Long userId, RoomSetting roomSetting) { public void updateSelectiveSettingByUserId(Long userId, RoomSetting roomSetting) {
mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)), Long roomId = getRoomId(userId);
getUpdateSelectiveSetting(getRoomSettingByUserId(userId), roomSetting), if (Objects.isNull(roomId)) {
RoomProfileManager.class); return;
} }
mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
getUpdateSelectiveSetting(getRoomSettingById(roomId), roomSetting),
RoomProfileManager.class);
}
@Override @Override
public void updatePassword(Long roomId, String password) { public void updatePassword(Long roomId, String password) {
@ -486,12 +497,16 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
RoomProfileManager.class); RoomProfileManager.class);
} }
@Override @Override
public void updateRoomCoverByUserId(Long userId, String cover) { public void updateRoomCoverByUserId(Long userId, String cover) {
mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)), Long roomId = getRoomId(userId);
new Update().set("updateTime", TimestampUtils.now()) if (Objects.isNull(roomId)) {
.set("roomCover", cover), return;
RoomProfileManager.class); }
mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
new Update().set("updateTime", TimestampUtils.now())
.set("roomCover", cover),
RoomProfileManager.class);
} }
@Override @Override
@ -526,21 +541,29 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
RoomProfileManager.class); RoomProfileManager.class);
} }
@Override @Override
public void updateUserCountry(Long userId, String countryCode, String countryName) { public void updateUserCountry(Long userId, String countryCode, String countryName) {
mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)), Long roomId = getRoomId(userId);
new Update().set("updateTime", TimestampUtils.now()) if (Objects.isNull(roomId)) {
.set("countryCode", countryCode) return;
.set("countryName", countryName), }
mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
new Update().set("updateTime", TimestampUtils.now())
.set("countryCode", countryCode)
.set("countryName", countryName),
RoomProfileManager.class); RoomProfileManager.class);
} }
@Override @Override
public void updateUserLangCode(Long userId, String langCode) { public void updateUserLangCode(Long userId, String langCode) {
mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)), Long roomId = getRoomId(userId);
new Update().set("updateTime", TimestampUtils.now()) if (Objects.isNull(roomId)) {
.set("langCode", StringUtils.toUpperCase(langCode)), return;
RoomProfileManager.class); }
mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
new Update().set("updateTime", TimestampUtils.now())
.set("langCode", StringUtils.toUpperCase(langCode)),
RoomProfileManager.class);
} }
@Override @Override
@ -591,16 +614,40 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
RoomProfileManager.class); RoomProfileManager.class);
} }
@Override @Override
public void delUserRoom(Long userId) { public void delUserRoom(Long userId) {
mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)), mongoTemplate.updateMulti(currentRoomQueryByUserId(userId),
new Update().set("updateTime", TimestampUtils.now()) new Update().set("updateTime", TimestampUtils.now())
.set("del", Boolean.TRUE), .set("del", Boolean.TRUE),
RoomProfileManager.class); RoomProfileManager.class);
} }
private List<UsePropsDTO> filterPropsNotAvailable(List<UsePropsDTO> useProps) { private Query currentRoomQueryByUserId(Long userId) {
if (CollectionUtils.isNotEmpty(useProps)) { 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<Long> 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<UsePropsDTO> filterPropsNotAvailable(List<UsePropsDTO> useProps) {
if (CollectionUtils.isNotEmpty(useProps)) {
return useProps.stream().filter(badge -> checkAvailable(badge.getExpireTime())) return useProps.stream().filter(badge -> checkAvailable(badge.getExpireTime()))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }

View File

@ -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<String, String> 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<Query> 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<RoomProfile> 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<Query> queryCaptor = ArgumentCaptor.forClass(Query.class);
verify(mongoTemplate).updateFirst(queryCaptor.capture(), any(), eq(RoomProfileManager.class));
assertEquals(99L, queryCaptor.getValue().getQueryObject().getLong("id"));
}
}