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

@ -40,6 +40,12 @@
<artifactId>business-rocketmq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<parent>

View File

@ -1,6 +1,5 @@
package com.red.circle.other.infra.database.mongo.service.live.impl;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.mongodb.BasicDBObject;
import com.red.circle.common.business.core.ReplaceString;
@ -25,6 +24,7 @@ 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.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -109,7 +109,7 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
@Override
public boolean existsUserRoom(Long userId) {
return mongoTemplate.exists(Query.query(Criteria.where("userId").is(userId)),
return mongoTemplate.exists(currentRoomQueryByUserId(userId),
RoomProfileManager.class);
}
@ -129,7 +129,7 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
@Override
public Long getRoomId(Long userId) {
Query query = Query.query(Criteria.where("userId").is(userId));
Query query = currentRoomQueryByUserId(userId);
query.fields().include("id");
return Optional.ofNullable(mongoTemplate.findOne(query, RoomProfileManager.class))
.map(RoomProfileManager::getId)
@ -155,7 +155,7 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
@Override
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));
return mongoTemplate.findOne(query,
RoomProfileManager.class);
@ -171,7 +171,7 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
@Override
public RoomProfileManager getByUserId(Long userId) {
return filterExpireTimeDecorate(
mongoTemplate.findOne(Query.query(Criteria.where("userId").is(userId)),
mongoTemplate.findOne(currentRoomQueryByUserId(userId),
RoomProfileManager.class));
}
@ -249,15 +249,22 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
@Override
public List<RoomProfile> listProfileByUserIds(Set<Long> userIds) {
System.out.println("id信息"+ JSON.toJSONString(userIds));
if (CollectionUtils.isEmpty(userIds)) {
return Lists.newArrayList();
}
Query query = Query.query(Criteria.where("userId").in(userIds));
Query query = currentRoomQueryByUserIds(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);
List<RoomProfileManager> rooms = mongoTemplate.find(query, RoomProfileManager.class);
if (CollectionUtils.isEmpty(rooms)) {
return 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
@ -360,7 +367,7 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
@Override
public RoomSetting getRoomSettingByUserId(Long userId) {
Query query = Query.query(Criteria.where("userId").is(userId));
Query query = currentRoomQueryByUserId(userId);
query.fields().include("setting");
return Optional.ofNullable(mongoTemplate.findOne(query,
RoomProfileManager.class))
@ -380,7 +387,7 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
@Override
public RoomCounter getRoomCounterByUserId(Long userId) {
Query query = Query.query(Criteria.where("userId").is(userId));
Query query = currentRoomQueryByUserId(userId);
query.fields().include("counter");
return Optional.ofNullable(mongoTemplate.findOne(query,
RoomProfileManager.class))
@ -473,8 +480,12 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
@Override
public void updateSelectiveSettingByUserId(Long userId, RoomSetting roomSetting) {
mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)),
getUpdateSelectiveSetting(getRoomSettingByUserId(userId), 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);
}
@ -488,7 +499,11 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
@Override
public void updateRoomCoverByUserId(Long userId, String cover) {
mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)),
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);
@ -528,7 +543,11 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
@Override
public void updateUserCountry(Long userId, String countryCode, String countryName) {
mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)),
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),
@ -537,7 +556,11 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
@Override
public void updateUserLangCode(Long userId, String langCode) {
mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)),
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);
@ -593,12 +616,36 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
@Override
public void delUserRoom(Long userId) {
mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(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<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()))

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"));
}
}