房间列表新增在线用户字段
This commit is contained in:
parent
931835a4b5
commit
69f77f1193
@ -10,10 +10,12 @@ import com.red.circle.other.app.common.room.RoomVoiceProfileCommon;
|
||||
import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO;
|
||||
import com.red.circle.other.app.service.game.GameLudoService;
|
||||
import com.red.circle.other.app.service.room.RocketStatusCacheService;
|
||||
import com.red.circle.other.app.dto.clientobject.room.OnlineUserCO;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserSVipGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.infra.database.cache.service.other.MicUserCacheService;
|
||||
import com.red.circle.other.domain.rocket.RocketStatus;
|
||||
import com.red.circle.other.infra.database.cache.service.user.RegionRoomCacheService;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.ActiveVoiceRoom;
|
||||
@ -63,6 +65,7 @@ public class RoomVoiceDiscoverQryExe {
|
||||
private final RocketStatusCacheService rocketStatusCacheService;
|
||||
private final GameLudoService gameLudoService;
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
private final MicUserCacheService micUserCacheService;
|
||||
|
||||
private static final String EMPTY_ROOM_CACHE_KEY = "empty_room_cache:*";
|
||||
|
||||
@ -119,6 +122,8 @@ public class RoomVoiceDiscoverQryExe {
|
||||
fillRocketStatus(roomList);
|
||||
// 填充游戏图标
|
||||
fillGameIcon(roomList);
|
||||
// 填充在线用户
|
||||
fillOnlineUsers(roomList);
|
||||
|
||||
return roomList;
|
||||
}
|
||||
@ -132,6 +137,39 @@ public class RoomVoiceDiscoverQryExe {
|
||||
roomList.forEach(room -> room.setRoomGameIcon(coverMap.get(room.getId())));
|
||||
}
|
||||
|
||||
private void fillOnlineUsers(List<RoomVoiceProfileCO> roomList) {
|
||||
if (CollectionUtils.isEmpty(roomList)) {
|
||||
return;
|
||||
}
|
||||
List<Long> roomIds = roomList.stream().map(RoomVoiceProfileCO::getId).toList();
|
||||
|
||||
// 每个房间取在线用户 userId(纯 Redis,无 RPC)
|
||||
Map<Long, List<Long>> roomOnlineUserIdsMap = roomIds.stream()
|
||||
.collect(Collectors.toMap(roomId -> roomId, micUserCacheService::listUser));
|
||||
|
||||
// 汇总所有 userId,单次 RPC 批量拉取用户资料
|
||||
Set<Long> allUserIds = roomOnlineUserIdsMap.values().stream()
|
||||
.flatMap(List::stream)
|
||||
.collect(Collectors.toSet());
|
||||
Map<Long, UserProfile> userProfileMap = CollectionUtils.isEmpty(allUserIds)
|
||||
? Map.of()
|
||||
: userProfileGateway.mapByUserIds(allUserIds);
|
||||
|
||||
roomList.forEach(room -> {
|
||||
List<OnlineUserCO> onlineUsers = roomOnlineUserIdsMap
|
||||
.getOrDefault(room.getId(), List.of())
|
||||
.stream()
|
||||
.map(userProfileMap::get)
|
||||
.filter(Objects::nonNull)
|
||||
.map(p -> new OnlineUserCO()
|
||||
.setId(p.getId())
|
||||
.setAccount(p.getAccount())
|
||||
.setUserAvatar(p.getUserAvatar()))
|
||||
.collect(Collectors.toList());
|
||||
room.setOnlineUsers(onlineUsers);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充房间的火箭状态信息
|
||||
*
|
||||
|
||||
@ -3,15 +3,20 @@ package com.red.circle.other.app.command.room.query;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.red.circle.common.business.dto.cmd.app.AppFlowCmd;
|
||||
import com.red.circle.other.app.common.room.RoomVoiceProfileCommon;
|
||||
import com.red.circle.other.app.dto.clientobject.room.OnlineUserCO;
|
||||
import com.red.circle.other.app.dto.clientobject.room.RoomBrowseRecordsV2CO;
|
||||
import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO;
|
||||
import com.red.circle.other.app.service.game.GameLudoService;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.infra.database.cache.service.other.MicUserCacheService;
|
||||
import com.red.circle.other.infra.database.rds.entity.live.RoomSubscription;
|
||||
import com.red.circle.other.infra.database.rds.service.live.RoomSubscriptionService;
|
||||
import com.red.circle.tool.core.collection.CollectionUtils;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -28,6 +33,8 @@ public class UserFollowRoomsQryExe {
|
||||
private final RoomVoiceProfileCommon roomVoiceProfileCommon;
|
||||
private final RoomSubscriptionService roomSubscriptionService;
|
||||
private final GameLudoService gameLudoService;
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
private final MicUserCacheService micUserCacheService;
|
||||
|
||||
public List<RoomBrowseRecordsV2CO> execute(AppFlowCmd cmd) {
|
||||
List<RoomSubscription> roomSubscriptions = roomSubscriptionService
|
||||
@ -44,19 +51,43 @@ public class UserFollowRoomsQryExe {
|
||||
roomSubscriptions.stream().map(RoomSubscription::getRoomId).collect(Collectors.toSet()));
|
||||
|
||||
// 填充游戏图标
|
||||
List<Long> list = roomSubscriptions.stream().map(RoomSubscription::getRoomId).toList();
|
||||
Map<Long, String> coverMap = gameLudoService.listGameCoverByRoomIds(list);
|
||||
List<Long> roomIds = roomSubscriptions.stream().map(RoomSubscription::getRoomId).toList();
|
||||
Map<Long, String> coverMap = gameLudoService.listGameCoverByRoomIds(roomIds);
|
||||
|
||||
// 每个房间取在线用户 userId(纯 Redis,无 RPC)
|
||||
Map<Long, List<Long>> roomOnlineUserIdsMap = roomIds.stream()
|
||||
.collect(Collectors.toMap(roomId -> roomId, micUserCacheService::listUser));
|
||||
|
||||
// 汇总所有 userId,单次 RPC 批量拉取用户资料
|
||||
Set<Long> allUserIds = roomOnlineUserIdsMap.values().stream()
|
||||
.flatMap(List::stream)
|
||||
.collect(Collectors.toSet());
|
||||
Map<Long, UserProfile> userProfileMap = CollectionUtils.isEmpty(allUserIds)
|
||||
? Map.of()
|
||||
: userProfileGateway.mapByUserIds(allUserIds);
|
||||
|
||||
return roomSubscriptions.stream().map(roomMember -> {
|
||||
RoomVoiceProfileCO profileCO = roomProfileMap.get(roomMember.getRoomId());
|
||||
if (profileCO != null) {
|
||||
profileCO.setRoomGameIcon(coverMap.get(roomMember.getRoomId()));
|
||||
}
|
||||
return new RoomBrowseRecordsV2CO()
|
||||
.setId(roomMember.getId())
|
||||
.setRoomProfile(profileCO);
|
||||
})
|
||||
.filter(sub -> Objects.nonNull(sub.getRoomProfile())).collect(Collectors.toList());
|
||||
RoomVoiceProfileCO profileCO = roomProfileMap.get(roomMember.getRoomId());
|
||||
if (profileCO != null) {
|
||||
profileCO.setRoomGameIcon(coverMap.get(roomMember.getRoomId()));
|
||||
}
|
||||
List<OnlineUserCO> onlineUsers = roomOnlineUserIdsMap
|
||||
.getOrDefault(roomMember.getRoomId(), List.of())
|
||||
.stream()
|
||||
.map(userProfileMap::get)
|
||||
.filter(Objects::nonNull)
|
||||
.map(p -> new OnlineUserCO()
|
||||
.setId(p.getId())
|
||||
.setAccount(p.getAccount())
|
||||
.setUserAvatar(p.getUserAvatar()))
|
||||
.collect(Collectors.toList());
|
||||
return new RoomBrowseRecordsV2CO()
|
||||
.setId(roomMember.getId())
|
||||
.setRoomProfile(profileCO)
|
||||
.setOnlineUsers(onlineUsers);
|
||||
})
|
||||
.filter(sub -> Objects.nonNull(sub.getRoomProfile()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -165,7 +165,6 @@ public class GiftAnchorCountStrategy implements GiftStrategy {
|
||||
|
||||
}
|
||||
//yoloSalaryDiamondCount(runningWater, giftAcceptUsers.get(0));
|
||||
log.warn("发送通知,更新代理工资数据,团队Ids:{}", teamIds);
|
||||
// 发送通知,更新代理工资数据
|
||||
if (CollectionUtils.isNotEmpty(teamIds)) {
|
||||
// teamSalaryMqMessage.sendSalaryCount(teamIds);
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
package com.red.circle.other.app.dto.clientobject.room;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.red.circle.framework.dto.ClientObject;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 房间在线用户简要信息.
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class OnlineUserCO extends ClientObject {
|
||||
|
||||
/**
|
||||
* 用户 id.
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 账号.
|
||||
*/
|
||||
private String account;
|
||||
|
||||
/**
|
||||
* 头像.
|
||||
*/
|
||||
private String userAvatar;
|
||||
}
|
||||
@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.red.circle.framework.dto.ClientObject;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
@ -30,4 +31,9 @@ public class RoomBrowseRecordsV2CO extends ClientObject {
|
||||
*/
|
||||
private RoomVoiceProfileCO roomProfile;
|
||||
|
||||
/**
|
||||
* 房间在线用户列表.
|
||||
*/
|
||||
private List<OnlineUserCO> onlineUsers;
|
||||
|
||||
}
|
||||
|
||||
@ -146,6 +146,11 @@ public class RoomVoiceProfileCO extends ClientObject {
|
||||
*/
|
||||
private Long rocketEnergy;
|
||||
|
||||
/**
|
||||
* 房间在线用户列表.
|
||||
*/
|
||||
private List<OnlineUserCO> onlineUsers;
|
||||
|
||||
/**
|
||||
* 设置房间成员数量.
|
||||
*/
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
package com.red.circle.other.infra.database.cache.key;
|
||||
|
||||
import com.red.circle.component.redis.RedisKeys;
|
||||
|
||||
/**
|
||||
* 麦克风在线用户缓存 key(与 live 服务共用同一 Redis hash).
|
||||
*/
|
||||
public enum MicUserKey implements RedisKeys {
|
||||
|
||||
/**
|
||||
* 房间用户.
|
||||
*/
|
||||
ROOM;
|
||||
|
||||
@Override
|
||||
public String businessPrefix() {
|
||||
// 必须与 live 服务 LiveMicUserKey.businessPrefix() 保持一致
|
||||
return "LMUser";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String businessKey() {
|
||||
return this.name();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.red.circle.other.infra.database.cache.service.other;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 房间在线用户缓存服务(只读,数据由 live 服务写入).
|
||||
*/
|
||||
public interface MicUserCacheService {
|
||||
|
||||
/**
|
||||
* 获取房间在线用户 userId 列表.
|
||||
*/
|
||||
List<Long> listUser(Long roomId);
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package com.red.circle.other.infra.database.cache.service.other.impl;
|
||||
|
||||
import com.red.circle.component.redis.service.RedisService;
|
||||
import com.red.circle.other.infra.database.cache.key.MicUserKey;
|
||||
import com.red.circle.other.infra.database.cache.service.other.MicUserCacheService;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 房间在线用户缓存服务实现.
|
||||
*
|
||||
* <p>live 服务以 userId 字符串为 hash field 写入,直接取 field 名集合即可,
|
||||
* 无需引入 live-domain 依赖,也无需反序列化。
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MicUserCacheServiceImpl implements MicUserCacheService {
|
||||
|
||||
private final RedisService redisService;
|
||||
|
||||
@Override
|
||||
public List<Long> listUser(Long roomId) {
|
||||
Set<String> fields = redisService.hashKeys(MicUserKey.ROOM.getKey(roomId));
|
||||
if (fields == null || fields.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
return fields.stream()
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.map(Long::valueOf)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.red.circle.OtherServiceApplication;
|
||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||
import com.red.circle.other.app.listener.team.TeamBillSettleListener;
|
||||
import com.red.circle.other.app.scheduler.AdminSalarySettlementTask;
|
||||
import com.red.circle.other.app.scheduler.BdLeaderSalarySettlementTask;
|
||||
import com.red.circle.other.app.scheduler.BdSalarySettlementTask;
|
||||
@ -42,86 +43,52 @@ public class BdSettlementTest {
|
||||
private MongoTemplate mongoTemplate;
|
||||
@Autowired
|
||||
private UserSalaryAccountClient userSalaryAccountClient;
|
||||
|
||||
@Autowired
|
||||
private TeamBillSettleListener teamBillSettleListener;
|
||||
|
||||
/**
|
||||
* BD 工资结算
|
||||
* 批量团队结算
|
||||
*/
|
||||
@Test
|
||||
public void testBdSettlement() {
|
||||
Integer billBelong = TeamBillCycleUtils.getCalcBillBelong();
|
||||
|
||||
bdSalarySettlementTask.processBdSalarySettlementTest(billBelong);
|
||||
|
||||
public void processTeamBillSettle() {
|
||||
String json = "['2043970266712944642', '2042485790634393602']";
|
||||
List<String> teamList = JSON.parseArray(json, String.class);
|
||||
for (String teamId : teamList) {
|
||||
Long id = Long.parseLong(teamId);
|
||||
teamBillSettleListener.processBillTest(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* BDLEADER 工资结算
|
||||
* BD 工资结算(指定用户)
|
||||
*/
|
||||
@Test
|
||||
public void testBdLeaderSettlement() {
|
||||
public void testBdSettlementByUserId() {
|
||||
String json = "['1963790037740466178', '1963790095911268354']";
|
||||
Integer billBelong = TeamBillCycleUtils.getCalcBillBelong();
|
||||
List<String> teamList = JSON.parseArray(json, String.class);
|
||||
|
||||
bdLeaderSalarySettlementTask.processBdLeaderSalarySettlementTest(billBelong);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdminSettlement() {
|
||||
adminSalarySettlementTask.processAdminSalarySettlementTest(TeamBillCycleUtils.getCalcBillBelong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssueSalary() {
|
||||
// Long bdUserId = 1963790037740466178L;
|
||||
// BdSalarySettlementRecord bdSalarySettlementRecord = new BdSalarySettlementRecord();
|
||||
// bdSalarySettlementRecord.setBillBelong(20251116);
|
||||
// bdSalarySettlementRecord.setSysOrigin(SysOriginPlatformEnum.ATYOU.name());
|
||||
// bdSalarySettlementRecord.setSettlementSalary(new BigDecimal(111));
|
||||
// bdSalarySettlementRecord.setId(IdWorkerUtils.getIdStr());
|
||||
// issueSalary(bdUserId, bdSalarySettlementRecord);
|
||||
|
||||
|
||||
Long bdLeaderUserId = 1963790037740466178L;
|
||||
BdLeaderSalarySettlementRecord bdLeaderSalarySettlementRecord = new BdLeaderSalarySettlementRecord();
|
||||
bdLeaderSalarySettlementRecord.setBillBelong(20251116);
|
||||
bdLeaderSalarySettlementRecord.setSysOrigin(SysOriginPlatformEnum.ATYOU.name());
|
||||
bdLeaderSalarySettlementRecord.setSettlementSalary(new BigDecimal(2));
|
||||
bdLeaderSalarySettlementRecord.setId(IdWorkerUtils.getIdStr());
|
||||
issueSalary(bdLeaderUserId, bdLeaderSalarySettlementRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发放BD工资
|
||||
*/
|
||||
private void issueSalary(Long bdUserId, BdSalarySettlementRecord record) {
|
||||
SalaryIssueInnerCmd innerCmd = new SalaryIssueInnerCmd();
|
||||
innerCmd.setBillBelong(record.getBillBelong());
|
||||
innerCmd.setUserId(bdUserId);
|
||||
innerCmd.setSysOrigin(record.getSysOrigin());
|
||||
innerCmd.setSalaryType("BD_SALARY");
|
||||
innerCmd.setEventDesc("SALARY_BD");
|
||||
innerCmd.setAmount(record.getSettlementSalary());
|
||||
innerCmd.setTrackId(record.getId());
|
||||
innerCmd.setBdId(bdUserId);
|
||||
userSalaryAccountClient.issueSalary(innerCmd);
|
||||
for (String userIdStr : teamList) {
|
||||
Long userId = Long.parseLong(userIdStr);
|
||||
// bdSalarySettlementTask.processBdSalarySettlementTestByUserId(userId, billBelong);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发放BDLEADER工资
|
||||
*/
|
||||
private void issueSalary(Long bdLeaderUserId, BdLeaderSalarySettlementRecord record) {
|
||||
SalaryIssueInnerCmd innerCmd = new SalaryIssueInnerCmd();
|
||||
innerCmd.setBillBelong(record.getBillBelong());
|
||||
innerCmd.setUserId(bdLeaderUserId);
|
||||
innerCmd.setSysOrigin(record.getSysOrigin());
|
||||
innerCmd.setSalaryType("BD_LEADER_SALARY");
|
||||
innerCmd.setEventDesc("SALARY_BD_LEADER");
|
||||
innerCmd.setAmount(record.getSettlementSalary());
|
||||
innerCmd.setTrackId(record.getId());
|
||||
innerCmd.setBdId(bdLeaderUserId);
|
||||
userSalaryAccountClient.issueSalary(innerCmd);
|
||||
|
||||
/**
|
||||
* BDLEADER 工资结算(指定用户)
|
||||
*/
|
||||
@Test
|
||||
public void testBdLeaderSettlementByUserId() {
|
||||
String json = "['1963790037740466178', '1963790095911268354']";
|
||||
Integer billBelong = TeamBillCycleUtils.getCalcBillBelong();
|
||||
List<String> teamList = JSON.parseArray(json, String.class);
|
||||
|
||||
for (String userIdStr : teamList) {
|
||||
Long userId = Long.parseLong(userIdStr);
|
||||
// bdLeaderSalarySettlementTask.processBdLeaderSalarySettlementTestByUserId(userId, billBelong);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user