房间置顶

This commit is contained in:
ZuoZuo 2026-05-01 17:35:31 +08:00
parent fc7d248171
commit e8975dca9d
14 changed files with 283 additions and 25 deletions

View File

@ -68,6 +68,7 @@ public class RoomVoiceDiscoverQryExe {
private static final String EMPTY_ROOM_CACHE_KEY = "empty_room_cache:*";
private static final String MEMBER_QUANTITY_EXT_KEY = "memberQuantity";
private static final String FIXED_WEIGHTS_EXT_KEY = "fixedWeights";
private static final int DISCOVERY_LIMIT = 50;
private static final long DISCOVERY_SLOW_STEP_MILLIS = 100L;
private static final long DISCOVERY_SLOW_TOTAL_MILLIS = 300L;
@ -164,7 +165,7 @@ public class RoomVoiceDiscoverQryExe {
DISCOVERY_LIMIT);
}
stepStart = logDiscoveryStep("fallback-room-profiles", stepStart, reqUserId, sysOrigin, region);
roomList = sortByMemberQuantityDesc(roomList);
roomList = sortByTopWeightAndMemberQuantityDesc(roomList);
stepStart = logDiscoveryStep("sort-rooms", stepStart, reqUserId, sysOrigin, region);
if (CollectionUtils.isEmpty(roomList)) {
@ -194,20 +195,30 @@ public class RoomVoiceDiscoverQryExe {
return roomList;
}
private List<RoomVoiceProfileCO> sortByMemberQuantityDesc(List<RoomVoiceProfileCO> roomList) {
private List<RoomVoiceProfileCO> sortByTopWeightAndMemberQuantityDesc(
List<RoomVoiceProfileCO> roomList) {
if (CollectionUtils.isEmpty(roomList)) {
return CollectionUtils.newArrayList();
}
return roomList.stream()
.sorted(Comparator.comparingInt(this::roomMemberQuantity).reversed())
.sorted(Comparator.comparingInt(this::roomFixedWeights).reversed()
.thenComparing(Comparator.comparingInt(this::roomMemberQuantity).reversed()))
.toList();
}
private int roomFixedWeights(RoomVoiceProfileCO room) {
return roomIntExtValue(room, FIXED_WEIGHTS_EXT_KEY);
}
private int roomMemberQuantity(RoomVoiceProfileCO room) {
return roomIntExtValue(room, MEMBER_QUANTITY_EXT_KEY);
}
private int roomIntExtValue(RoomVoiceProfileCO room, String key) {
if (Objects.isNull(room) || Objects.isNull(room.getExtValues())) {
return 0;
}
Object value = room.getExtValues().get(MEMBER_QUANTITY_EXT_KEY);
Object value = room.getExtValues().get(key);
if (value instanceof Number number) {
return Math.max(number.intValue(), 0);
}

View File

@ -19,6 +19,8 @@ import com.red.circle.other.infra.database.mongo.entity.live.assist.FamilyProfil
import com.red.circle.other.infra.database.mongo.service.live.ActiveVoiceRoomService;
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
import com.red.circle.other.infra.database.mongo.service.live.RoomTopFixedService;
import com.red.circle.other.infra.database.mongo.entity.user.region.SysRegionConfig;
import com.red.circle.other.infra.database.mongo.service.user.region.SysRegionConfigService;
import com.red.circle.other.infra.database.mongo.service.user.status.OnlineUserService;
import com.red.circle.other.infra.database.rds.entity.family.FamilyMemberInfo;
import com.red.circle.other.infra.database.rds.service.family.FamilyMemberInfoService;
@ -51,6 +53,7 @@ public class OnlineRoomCommon {
private final OnlineUserService onlineUserService;
private final UserProfileGateway userProfileGateway;
private final RoomTopFixedService roomTopFixedService;
private final SysRegionConfigService sysRegionConfigService;
private final HotRoomCacheService hotRoomCacheService;
private final ActiveVoiceRoomService activeVoiceRoomService;
private final FamilyMemberInfoService familyMemberInfoService;
@ -127,7 +130,7 @@ public class OnlineRoomCommon {
// ? ActiveVoiceRegion.LANG_AR
// : ActiveVoiceRegion.toRegion(userProfile.getCountryCode());
RoomTopFixed roomTopFixed = roomTopFixedService.getByRoomId(room.getId());
RoomTopFixed roomTopFixed = roomTopFixedService.getEffectiveByRoomId(room.getId());
Integer roomTopFixedWeights = Optional.ofNullable(roomTopFixed)
.map(fixed -> Objects.nonNull(fixed.getWeights()) ? fixed.getWeights() : 0)
.orElse(0);
@ -150,7 +153,7 @@ public class OnlineRoomCommon {
.setCountryCode(StringUtils.toUpperCase(userProfile.getCountryCode()))
.setCountryName(userProfile.getCountryName())
// ALL所有DEFAULT默认区域其他根据语言分割.
.setRegion(roomOwnRegionCode)
.setRegion(resolveActiveRoomRegion(roomOwnRegionCode, roomTopFixed))
.setExpiredTime(TimestampUtils.nowPlusMinutes(topRoomForeverOnline ? 60 : 3))
.setCreateTime(TimestampUtils.now())
.setUpdateTime(TimestampUtils.now())
@ -161,6 +164,16 @@ public class OnlineRoomCommon {
);
}
private String resolveActiveRoomRegion(String defaultRegionCode, RoomTopFixed roomTopFixed) {
if (Objects.isNull(roomTopFixed) || StringUtils.isBlank(roomTopFixed.getRegion())) {
return defaultRegionCode;
}
return Optional.ofNullable(sysRegionConfigService.getById(roomTopFixed.getRegion()))
.map(SysRegionConfig::getRegionCode)
.filter(StringUtils::isNotBlank)
.orElse(defaultRegionCode);
}
private FamilyProfile getFamilyProfile(Long userId) {
FamilyMemberInfo memberInfo = familyMemberInfoService.getFamilyMemberByUserId(userId);

View File

@ -56,16 +56,18 @@ public class RoomRegionFilterCommon {
public List<ActiveVoiceRoom> filterActiveVoiceRoomsByRegion(
List<ActiveVoiceRoom> activeVoiceRooms, String regionCode) {
return filterByRegionCode(activeVoiceRooms, ActiveVoiceRoom::getUserId, regionCode);
return filterByRegionCode(activeVoiceRooms, ActiveVoiceRoom::getUserId,
ActiveVoiceRoom::getRegion, regionCode);
}
public List<RoomProfileManager> filterRoomProfileManagersByRegion(
List<RoomProfileManager> roomProfileManagers, String regionCode) {
return filterByRegionCode(roomProfileManagers, RoomProfileManager::getUserId, regionCode);
return filterByRegionCode(roomProfileManagers, RoomProfileManager::getUserId,
item -> null, regionCode);
}
private <T> List<T> filterByRegionCode(List<T> source, Function<T, Long> userIdGetter,
String regionCode) {
Function<T, String> regionCodeGetter, String regionCode) {
if (CollectionUtils.isEmpty(source) || StringUtils.isBlank(regionCode)) {
return Lists.newArrayList();
}
@ -84,7 +86,8 @@ public class RoomRegionFilterCommon {
}
return source.stream()
.filter(item -> StringUtils.equalsIgnoreCase(regionCode, regionCodeMap.get(userIdGetter.apply(item))))
.filter(item -> StringUtils.equalsIgnoreCase(regionCode, regionCodeGetter.apply(item))
|| StringUtils.equalsIgnoreCase(regionCode, regionCodeMap.get(userIdGetter.apply(item))))
.toList();
}
}

View File

@ -152,6 +152,7 @@ public class RoomVoiceProfileCommon {
return null;
}
roomVoiceProfile.putRoomMemberQuantity(toRoomMemberQuantity(activeVoiceRoom.getOnlineQuantity()));
roomVoiceProfile.putFixedWeights(activeVoiceRoom.getFixedWeights());
roomVoiceProfile.setHotRoom(activeVoiceRoom.getHot());
roomVoiceProfile.setRoomGameIcon("");
roomVoiceProfile.setUserSVipLevel(SVIPLevelEnum.valueOf(activeVoiceRoom.getSuperVipLevel()));

View File

@ -124,6 +124,88 @@ class RoomVoiceDiscoverQryExeTest {
verify(activeVoiceRoomService, never()).listDiscover("YOLO", true, "AE", null, 50);
}
@Test
void execute_shouldKeepTopRoomBeforeHigherMemberRoom() {
UserSVipGateway userSVipGateway = mock(UserSVipGateway.class);
UserRegionGateway userRegionGateway = mock(UserRegionGateway.class);
RoomRegionFilterCommon roomRegionFilterCommon = mock(RoomRegionFilterCommon.class);
RoomVoiceProfileCommon roomVoiceProfileCommon = mock(RoomVoiceProfileCommon.class);
ActiveVoiceRoomService activeVoiceRoomService = mock(ActiveVoiceRoomService.class);
RoomUserBlacklistService roomUserBlacklistService = mock(RoomUserBlacklistService.class);
LatestMobileDeviceService latestMobileDeviceService = mock(LatestMobileDeviceService.class);
RoomProfileManagerService roomProfileManagerService = mock(RoomProfileManagerService.class);
RegionRoomCacheService regionRoomCacheService = mock(RegionRoomCacheService.class);
LiveMicClient liveMicClient = mock(LiveMicClient.class);
RedisTemplate<String, Object> redisTemplate = mock(RedisTemplate.class);
RocketStatusCacheService rocketStatusCacheService = mock(RocketStatusCacheService.class);
GameLudoService gameLudoService = mock(GameLudoService.class);
UserProfileGateway userProfileGateway = mock(UserProfileGateway.class);
CountryCodeAliasSupport countryCodeAliasSupport = mock(CountryCodeAliasSupport.class);
RoomVoiceDiscoverQryExe exe = new RoomVoiceDiscoverQryExe(
userSVipGateway,
userRegionGateway,
roomRegionFilterCommon,
roomVoiceProfileCommon,
activeVoiceRoomService,
roomUserBlacklistService,
latestMobileDeviceService,
roomProfileManagerService,
regionRoomCacheService,
liveMicClient,
redisTemplate,
rocketStatusCacheService,
gameLudoService,
userProfileGateway,
countryCodeAliasSupport
);
AppExtCommand cmd = new AppExtCommand();
cmd.setReqUserId(1L);
cmd.setReqSysOrigin(ReqSysOrigin.of("YOLO", "YOLO"));
RegionConfig currentRegion = new RegionConfig().setRegionCode("AE").setCountryCodes("AE,SA");
UserProfile userProfile = new UserProfile();
ActiveVoiceRoom activeVoiceRoom = new ActiveVoiceRoom().setId(101L).setUserId(201L);
RoomProfileManager fallbackRoomManager = new RoomProfileManager();
fallbackRoomManager.setId(102L);
fallbackRoomManager.setUserId(202L);
RoomVoiceProfileCO topRoomCo = new RoomVoiceProfileCO().setId(101L).setUserId(201L)
.putRoomMemberQuantity(0)
.putFixedWeights(100);
RoomVoiceProfileCO fallbackRoomCo = new RoomVoiceProfileCO().setId(102L).setUserId(202L)
.putRoomMemberQuantity(2);
when(roomRegionFilterCommon.requireRegionConfig(1L)).thenReturn(currentRegion);
when(userProfileGateway.getByUserId(1L)).thenReturn(userProfile);
when(regionRoomCacheService.getRegionsRoom("YOLOAE")).thenReturn(null);
when(activeVoiceRoomService.listByRegion("YOLO", "AE", 50)).thenReturn(List.of(activeVoiceRoom));
when(roomRegionFilterCommon.filterActiveVoiceRoomsByRegion(List.of(activeVoiceRoom), "AE"))
.thenReturn(List.of(activeVoiceRoom));
when(roomVoiceProfileCommon.toListRoomVoiceProfileCO(List.of(activeVoiceRoom))).thenReturn(
List.of(topRoomCo)
);
when(roomRegionFilterCommon.listCountryCodes(currentRegion)).thenReturn(List.of("AE", "SA"));
when(roomProfileManagerService.listSelectiveLimitByCountryCodes(
"YOLO", List.of("AE", "SA"), List.of(101L), 50
)).thenReturn(List.of(fallbackRoomManager));
when(roomRegionFilterCommon.filterRoomProfileManagersByRegion(
List.of(fallbackRoomManager), "AE"
)).thenReturn(List.of(fallbackRoomManager));
when(roomVoiceProfileCommon.listRoomVoiceProfilesV2(List.of(fallbackRoomManager))).thenReturn(
List.of(fallbackRoomCo)
);
when(userSVipGateway.checkSVipIdentity(anySet())).thenReturn(
Map.of(201L, SVIPLevelEnum.NONE, 202L, SVIPLevelEnum.NONE)
);
when(rocketStatusCacheService.batchGetRocketStatus(List.of(101L, 102L))).thenReturn(Map.of());
when(gameLudoService.listGameCoverByRoomIds(List.of(101L, 102L))).thenReturn(Map.of());
List<RoomVoiceProfileCO> roomList = exe.execute(cmd);
assertEquals(List.of(topRoomCo, fallbackRoomCo), roomList);
}
@Test
void execute_shouldReturnAllRegionRoomsForWhiteListUser() {
UserSVipGateway userSVipGateway = mock(UserSVipGateway.class);

View File

@ -34,6 +34,32 @@ class RoomRegionFilterCommonTest {
assertEquals(List.of(currentRegionRoom), filteredRooms);
}
@Test
void filterActiveVoiceRoomsByRegion_shouldKeepConfiguredRegionRooms() {
UserRegionGateway userRegionGateway = mock(UserRegionGateway.class);
RoomRegionFilterCommon roomRegionFilterCommon = new RoomRegionFilterCommon(userRegionGateway);
ActiveVoiceRoom topRegionRoom = new ActiveVoiceRoom()
.setId(1001L)
.setUserId(2001L)
.setRegion("AE");
ActiveVoiceRoom otherRegionRoom = new ActiveVoiceRoom()
.setId(1002L)
.setUserId(2002L)
.setRegion("SA");
when(userRegionGateway.mapRegionCode(Set.of(2001L, 2002L))).thenReturn(
Map.of(2001L, "SA", 2002L, "SA")
);
List<ActiveVoiceRoom> filteredRooms = roomRegionFilterCommon.filterActiveVoiceRoomsByRegion(
List.of(topRegionRoom, otherRegionRoom),
"AE"
);
assertEquals(List.of(topRegionRoom), filteredRooms);
}
@Test
void filterRoomProfileManagersByRegion_shouldKeepOnlyCurrentRegionRooms() {
UserRegionGateway userRegionGateway = mock(UserRegionGateway.class);

View File

@ -42,6 +42,7 @@ class RoomVoiceProfileCommonTest {
.setId(10001L)
.setUserId(20001L)
.setOnlineQuantity(6L)
.setFixedWeights(88)
.setSuperVipLevel("NONE");
RoomProfileManager roomProfileManager = new RoomProfileManager();
@ -75,6 +76,7 @@ class RoomVoiceProfileCommonTest {
assertEquals(1, roomProfiles.size());
assertEquals("6", getExtValue(roomProfiles.get(0), "memberQuantity"));
assertEquals(88, getExtValue(roomProfiles.get(0), "fixedWeights"));
}
private Object getExtValue(RoomVoiceProfileCO roomVoiceProfileCO, String key) {

View File

@ -154,6 +154,14 @@ public class RoomVoiceProfileCO extends ClientObject {
return this;
}
/**
* 设置房间置顶权重.
*/
public RoomVoiceProfileCO putFixedWeights(final Integer fixedWeights) {
putExtField("fixedWeights", Objects.isNull(fixedWeights) ? 0 : fixedWeights);
return this;
}
/**
* 是否存在密码.
*/

View File

@ -29,6 +29,11 @@ public interface RoomTopFixedService {
*/
RoomTopFixed getByRoomId(Long roomId);
/**
* 获取当前生效中的置顶房间.
*/
RoomTopFixed getEffectiveByRoomId(Long roomId);
/**
* 房间置顶权重.
*/

View File

@ -126,7 +126,7 @@ public class ActiveVoiceRoomServiceImpl implements ActiveVoiceRoomService {
if (Objects.nonNull(qryCmd.getOrderByStrategy())) {
query.with(
Sort.by(Stream.of("onlineQuantity", "fixedWeights", "weights").map(Order::desc)
Sort.by(Stream.of("fixedWeights", "onlineQuantity", "weights").map(Order::desc)
.toArray(Order[]::new)));
}
@ -174,9 +174,9 @@ public class ActiveVoiceRoomServiceImpl implements ActiveVoiceRoomService {
// 3. 排序逻辑
Aggregation.sort(Sort.by(
Sort.Order.desc("fixedWeightsScore"), // 如果区域不匹配fixedWeights 0不影响排序
Sort.Order.desc("onlineQuantity"),
Sort.Order.desc("regionMatchScore"),
Sort.Order.desc("fixedWeightsScore"), // 如果区域不匹配fixedWeights 0不影响排序
Sort.Order.desc("weights")
)),
@ -196,8 +196,8 @@ public class ActiveVoiceRoomServiceImpl implements ActiveVoiceRoomService {
Criteria.where("sysOrigin").is(sysOrigin)
.and("region").is(region)
).with(Sort.by(
Sort.Order.desc("onlineQuantity"),
Sort.Order.desc("fixedWeights"),
Sort.Order.desc("onlineQuantity"),
Sort.Order.desc("weights")
));

View File

@ -6,7 +6,9 @@ import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.other.infra.database.mongo.entity.live.RoomTopFixed;
import com.red.circle.other.infra.database.mongo.service.live.RoomTopFixedService;
import com.red.circle.other.inner.model.cmd.sys.RoomTopFixedQryCmd;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.sql.Timestamp;
import java.util.Objects;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
@ -44,7 +46,7 @@ public class RoomTopFixedServiceImpl implements RoomTopFixedService {
}
if (StringUtils.isNotBlank(query.getRegion())) {
criteria.and("region").lt(query.getRegion());
criteria.and("region").is(query.getRegion());
}
if (Objects.isNull(query.getLimit())) {
@ -64,13 +66,28 @@ public class RoomTopFixedServiceImpl implements RoomTopFixedService {
return mongoTemplate.findOne(Query.query(Criteria.where("id").is(roomId)), RoomTopFixed.class);
}
@Override
public RoomTopFixed getEffectiveByRoomId(Long roomId) {
return mongoTemplate.findOne(Query.query(effectiveCriteria(roomId)), RoomTopFixed.class);
}
@Override
public Integer getWeights(Long roomId) {
Query query = Query.query(Criteria.where("id").is(roomId));
query.fields().include("weights");
return Optional.ofNullable(mongoTemplate.findOne(query, RoomTopFixed.class))
return Optional.ofNullable(getEffectiveByRoomId(roomId))
.map(top -> Objects.nonNull(top.getWeights()) ? top.getWeights() : 0)
.orElse(0);
}
private Criteria effectiveCriteria(Long roomId) {
Timestamp now = TimestampUtils.now();
return new Criteria().andOperator(
Criteria.where("id").is(roomId),
Criteria.where("startTime").lte(now),
new Criteria().orOperator(
Criteria.where("expiredTime").is(null),
Criteria.where("expiredTime").gt(now)
)
);
}
}

View File

@ -43,15 +43,15 @@ class ActiveVoiceRoomServiceImplTest {
assertEquals(50, query.getLimit());
Document sortObject = query.getSortObject();
assertIterableEquals(List.of("onlineQuantity", "fixedWeights", "weights"),
assertIterableEquals(List.of("fixedWeights", "onlineQuantity", "weights"),
sortObject.keySet());
assertEquals(-1, sortObject.getInteger("onlineQuantity"));
assertEquals(-1, sortObject.getInteger("fixedWeights"));
assertEquals(-1, sortObject.getInteger("onlineQuantity"));
assertEquals(-1, sortObject.getInteger("weights"));
}
@Test
void listOps_shouldUseOnlineQuantityFirstForDiscoverySort() {
void listOps_shouldUseFixedWeightsFirstForDiscoverySort() {
ArgumentCaptor<Query> queryCaptor = ArgumentCaptor.forClass(Query.class);
when(mongoTemplate.find(queryCaptor.capture(), eq(ActiveVoiceRoom.class))).thenReturn(List.of());
@ -63,10 +63,10 @@ class ActiveVoiceRoomServiceImplTest {
service.listOps(cmd);
Document sortObject = queryCaptor.getValue().getSortObject();
assertIterableEquals(List.of("onlineQuantity", "fixedWeights", "weights"),
assertIterableEquals(List.of("fixedWeights", "onlineQuantity", "weights"),
sortObject.keySet());
assertEquals(-1, sortObject.getInteger("onlineQuantity"));
assertEquals(-1, sortObject.getInteger("fixedWeights"));
assertEquals(-1, sortObject.getInteger("onlineQuantity"));
assertEquals(-1, sortObject.getInteger("weights"));
}
}

View File

@ -14,6 +14,8 @@ import com.red.circle.other.infra.database.mongo.entity.live.*;
import com.red.circle.other.infra.database.mongo.service.live.ActiveVoiceRoomService;
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
import com.red.circle.other.infra.database.mongo.service.live.RoomTopFixedService;
import com.red.circle.other.infra.database.mongo.entity.user.region.SysRegionConfig;
import com.red.circle.other.infra.database.mongo.service.user.region.SysRegionConfigService;
import com.red.circle.other.inner.model.cmd.live.AppActiveVoiceRoomQryCmd;
import com.red.circle.other.inner.model.dto.live.ActiveVoiceRoomDTO;
import java.util.List;
@ -43,6 +45,7 @@ public class ActiveVoiceRoomClientServiceImpl implements ActiveVoiceRoomClientSe
private final UserProfileGateway userProfileGateway;
private final UserRegionGateway userRegionGateway;
private final RoomTopFixedService roomTopFixedService;
private final SysRegionConfigService sysRegionConfigService;
@Override
public Long count(String sysOrigin) {
@ -62,7 +65,7 @@ public class ActiveVoiceRoomClientServiceImpl implements ActiveVoiceRoomClientSe
UserProfile userProfile = userProfileGateway.getByUserId(room.getUserId());
String roomOwnRegionCode = userRegionGateway.getRegionCode(room.getUserId());
RoomTopFixed roomTopFixed = roomTopFixedService.getByRoomId(room.getId());
RoomTopFixed roomTopFixed = roomTopFixedService.getEffectiveByRoomId(room.getId());
Integer roomTopFixedWeights = Optional.ofNullable(roomTopFixed)
.map(fixed -> Objects.nonNull(fixed.getWeights()) ? fixed.getWeights() : 0)
.orElse(0);
@ -89,7 +92,7 @@ public class ActiveVoiceRoomClientServiceImpl implements ActiveVoiceRoomClientSe
.setCountryCode(StringUtils.toUpperCase(userProfile.getCountryCode()))
.setCountryName(userProfile.getCountryName())
// ALL所有DEFAULT默认区域其他根据语言分割.
.setRegion(roomOwnRegionCode)
.setRegion(resolveActiveRoomRegion(roomOwnRegionCode, roomTopFixed))
.setExpiredTime(TimestampUtils.nowPlusMinutes(topRoomForeverOnline ? 60 : 3))
.setCreateTime(TimestampUtils.now())
.setUpdateTime(TimestampUtils.now())
@ -100,5 +103,15 @@ public class ActiveVoiceRoomClientServiceImpl implements ActiveVoiceRoomClientSe
);
}
private String resolveActiveRoomRegion(String defaultRegionCode, RoomTopFixed roomTopFixed) {
if (Objects.isNull(roomTopFixed) || StringUtils.isBlank(roomTopFixed.getRegion())) {
return defaultRegionCode;
}
return Optional.ofNullable(sysRegionConfigService.getById(roomTopFixed.getRegion()))
.map(SysRegionConfig::getRegionCode)
.filter(StringUtils::isNotBlank)
.orElse(defaultRegionCode);
}
}

View File

@ -3,16 +3,21 @@ package com.red.circle.other.app.inner.service.live.impl;
import com.red.circle.common.business.dto.cmd.PageRoomIdCmd;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.other.app.common.live.OnlineRoomCommon;
import com.red.circle.other.app.inner.convertor.live.RoomProfileInnerConvertor;
import com.red.circle.other.app.inner.service.live.HotRoomClientService;
import com.red.circle.other.infra.database.cache.service.other.SetHotRoomCacheService;
import com.red.circle.other.infra.database.cache.service.user.RegionRoomCacheService;
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.entity.live.RoomTopFixed;
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
import com.red.circle.other.infra.database.mongo.service.live.RoomTopFixedService;
import com.red.circle.other.infra.database.mongo.entity.user.region.SysRegionConfig;
import com.red.circle.other.infra.database.mongo.service.user.region.SysRegionConfigService;
import com.red.circle.other.infra.database.rds.entity.live.HotRoom;
import com.red.circle.other.infra.database.rds.service.live.HotRoomService;
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
import com.red.circle.other.inner.asserts.RoomErrorCode;
import com.red.circle.other.inner.model.cmd.sys.RoomTopFixedCmd;
import com.red.circle.other.inner.model.cmd.sys.RoomTopFixedQryCmd;
@ -21,15 +26,21 @@ import com.red.circle.other.inner.model.dto.sys.SysHotRoomDTO;
import com.red.circle.other.inner.model.dto.sys.SysTopRoomDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @author lisizhe on 2020/12/11
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class HotRoomClientServiceImpl implements HotRoomClientService {
@ -38,8 +49,11 @@ public class HotRoomClientServiceImpl implements HotRoomClientService {
private final RoomTopFixedService roomTopFixedService;
private final SysRegionConfigService sysRegionConfigService;
private final SetHotRoomCacheService setHotRoomCacheService;
private final RegionRoomCacheService regionRoomCacheService;
private final RoomProfileInnerConvertor roomProfileInnerConvertor;
private final RoomProfileManagerService roomProfileManagerService;
private final OnlineRoomCommon onlineRoomCommon;
private final UserRegionGateway userRegionGateway;
@Override
public void addOrUpdate(SysHotRoomCmd param) {
@ -124,11 +138,74 @@ public class HotRoomClientServiceImpl implements HotRoomClientService {
public void addOrUpdateRoomTop(RoomTopFixedCmd param) {
RoomProfile roomProfile = roomProfileManagerService.getProfileById(param.getId());
ResponseAssert.notNull(RoomErrorCode.ROOM_NOT_EXISTS, roomProfile);
roomTopFixedService.add(roomProfileInnerConvertor.toRoomTopFixed(param));
RoomTopFixed oldRoomTopFixed = roomTopFixedService.getByRoomId(param.getId());
RoomTopFixed newRoomTopFixed = roomProfileInnerConvertor.toRoomTopFixed(param);
roomTopFixedService.add(newRoomTopFixed);
refreshActiveRoom(param.getId());
removeDiscoveryCache(param.getId(), oldRoomTopFixed, newRoomTopFixed);
}
@Override
public void removeRoomTop(Long roomId) {
RoomTopFixed oldRoomTopFixed = roomTopFixedService.getByRoomId(roomId);
roomTopFixedService.removeById(roomId);
refreshActiveRoom(roomId);
removeDiscoveryCache(roomId, oldRoomTopFixed);
}
private void refreshActiveRoom(Long roomId) {
try {
onlineRoomCommon.addHeartbeatOnlineRoomProfileById(roomId);
} catch (Exception e) {
log.warn("刷新置顶房间在线数据失败 roomId={}", roomId, e);
}
}
private void removeDiscoveryCache(Long roomId, RoomTopFixed... roomTopFixedConfigs) {
try {
Map<String, Set<String>> regionsBySysOrigin = new HashMap<>();
appendTopRoomRegions(regionsBySysOrigin, roomTopFixedConfigs);
appendOwnerRegion(regionsBySysOrigin, roomId);
regionsBySysOrigin.forEach((sysOrigin, regions) -> regions.forEach(regionCode -> {
regionRoomCacheService.remove(sysOrigin + regionCode);
regionRoomCacheService.remove(sysOrigin + regionCode + ":ALL_REGION");
}));
} catch (Exception e) {
log.warn("清理置顶房间发现缓存失败 roomId={}", roomId, e);
}
}
private void appendTopRoomRegions(Map<String, Set<String>> regionsBySysOrigin,
RoomTopFixed... roomTopFixedConfigs) {
if (Objects.isNull(roomTopFixedConfigs)) {
return;
}
for (RoomTopFixed roomTopFixed : roomTopFixedConfigs) {
if (Objects.isNull(roomTopFixed) || StringUtils.isBlank(roomTopFixed.getSysOrigin())
|| StringUtils.isBlank(roomTopFixed.getRegion())) {
continue;
}
SysRegionConfig regionConfig = sysRegionConfigService.getById(roomTopFixed.getRegion());
if (Objects.isNull(regionConfig) || StringUtils.isBlank(regionConfig.getRegionCode())) {
continue;
}
regionsBySysOrigin.computeIfAbsent(roomTopFixed.getSysOrigin(), key -> new HashSet<>())
.add(regionConfig.getRegionCode());
}
}
private void appendOwnerRegion(Map<String, Set<String>> regionsBySysOrigin, Long roomId) {
RoomProfileManager roomProfile = roomProfileManagerService.getById(roomId);
if (Objects.isNull(roomProfile) || StringUtils.isBlank(roomProfile.getSysOrigin())
|| Objects.isNull(roomProfile.getUserId())) {
return;
}
String ownerRegionCode = userRegionGateway.getRegionCode(roomProfile.getUserId());
if (StringUtils.isBlank(ownerRegionCode)) {
return;
}
regionsBySysOrigin.computeIfAbsent(roomProfile.getSysOrigin(), key -> new HashSet<>())
.add(ownerRegionCode);
}
}