fix(live): 修复上麦 goUp 的 NPE 风险、异常吞噬和重复 HTTP 调用
P0 - BUG 修复: - 将 liveMicrophone 和 micUser 的 null 检查移至使用前,彻底消除 NPE 风险 - 替换 catch(Exception) 全吞逻辑:业务异常直接上抛保留原始错误码, 不再将所有错误误报为"麦克风已被占用",改用 log.error 记录完整堆栈 P1 - 性能优化: - checkMicAvailableUse 前移至加锁后第一步,麦位已占时提前返回, 避免后续 5 次 HTTP 调用空跑 - userProfileClient.getByUserId 由 2 次减为 1 次: 先获取 UserProfileDTO 后直接传给 toLiveMicUser, 删除 getLiveMicUser 内部的重复调用 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> (cherry picked from commit 8e9ca4f3434762969e7bbe76d69dc64aec08df89)
This commit is contained in:
parent
e36a28cf85
commit
49281d503a
@ -42,6 +42,7 @@ import com.red.circle.other.inner.model.cmd.live.LiveHeartbeatCmd;
|
||||
import com.red.circle.other.inner.model.cmd.live.MemberRolesQryCmd;
|
||||
import com.red.circle.other.inner.model.dto.live.RoomProfileDTO;
|
||||
import com.red.circle.other.inner.model.dto.live.RoomProfileManagerDTO;
|
||||
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
||||
import com.red.circle.other.inner.model.dto.user.WealthAndCharmLevelDTO;
|
||||
import com.red.circle.tool.core.collection.CollectionUtils;
|
||||
import com.red.circle.tool.core.func.VoidConsumer;
|
||||
@ -159,27 +160,38 @@ public class LiveMicrophoneGatewayImpl implements LiveMicrophoneGateway {
|
||||
|
||||
@Override
|
||||
public LiveMicrophoneNoticeDTO goUp(Long roomId, Integer micIndex, Long userId) {
|
||||
micOpsLock(roomId, micIndex);
|
||||
// RLock lock = redissonClient.getLock(roomId.toString()+micIndex.toString()+"room");
|
||||
// lock.lock();
|
||||
micOpsLock(roomId, micIndex);
|
||||
try {
|
||||
// 验证用户是否真实存在
|
||||
ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, userProfileClient.getByUserId(userId));
|
||||
|
||||
RoomProfileDTO roomProfile = roomManagerClient.getById(roomId).getBody();
|
||||
// 房间是否真实存在
|
||||
ResponseAssert.notNull(RoomErrorCode.ROOM_NOT_EXISTS, roomProfile);
|
||||
// 获取上麦克风需要数据
|
||||
LiveMicrophone liveMicrophone = getLiveMicrophone(roomId, micIndex, userId);
|
||||
liveMicrophone.getUser().setCharmLevel(userLevelClient.getUserLevel(SysOriginPlatformEnum.valueOf(roomProfile.getSysOrigin()),userId).getBody().getCharmLevel());
|
||||
ResponseAssert.notNull(LiveMicErrorCode.MIC_INDEX_NOT_FOUND, liveMicrophone);
|
||||
ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, liveMicrophone.getUser());
|
||||
// P1: 优先检查麦克风可用性,失败立即返回,避免后续 HTTP 调用空跑
|
||||
checkMicAvailableUse(roomId, micIndex);
|
||||
|
||||
// P1: 获取用户信息一次,后续复用,避免 getLiveMicUser 内部重复调用
|
||||
UserProfileDTO userProfile = userProfileClient.getByUserId(userId).getBody();
|
||||
ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, userProfile);
|
||||
|
||||
RoomProfileDTO roomProfile = roomManagerClient.getById(roomId).getBody();
|
||||
ResponseAssert.notNull(RoomErrorCode.ROOM_NOT_EXISTS, roomProfile);
|
||||
|
||||
// P0: 先判 null 再使用,避免 NPE 被 catch 吞掉误报为"麦克风已被占用"
|
||||
LiveMicSettingSeat micSeat = liveMicSettingService.getMicSeat(roomId, micIndex);
|
||||
ResponseAssert.notNull(LiveMicErrorCode.MIC_INDEX_NOT_FOUND, micSeat);
|
||||
|
||||
// P1: 直接用已有 userProfile 构建 micUser,跳过重复的 HTTP 调用
|
||||
LiveMicUser micUser = liveMicrophoneInfraConvertor.toLiveMicUser(userProfile);
|
||||
ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, micUser);
|
||||
micUser.setRoles(Objects.toString(roomMemberClient.getMemberRoles(roomId, userId).getBody()));
|
||||
micUser.setCharmLevel(userLevelClient.getUserLevel(
|
||||
SysOriginPlatformEnum.valueOf(roomProfile.getSysOrigin()), userId).getBody().getCharmLevel());
|
||||
|
||||
LiveMicrophone liveMicrophone = new LiveMicrophone()
|
||||
.setMicIndex(micSeat.getMicIndex())
|
||||
.setUser(micUser)
|
||||
.updateLastActivityTime();
|
||||
|
||||
// 下掉已上麦克风
|
||||
List<LiveMicrophone> lives = liveMicCacheService.listLiveMicrophone(roomId, userId);
|
||||
if (CollectionUtils.isNotEmpty(lives)) {
|
||||
liveMicCacheService.goDown(roomId,
|
||||
lives.stream().map(LiveMicrophone::getMicIndex).toList());
|
||||
liveMicCacheService.goDown(roomId, lives.stream().map(LiveMicrophone::getMicIndex).toList());
|
||||
}
|
||||
|
||||
// 上麦克风
|
||||
@ -190,13 +202,12 @@ public class LiveMicrophoneGatewayImpl implements LiveMicrophoneGateway {
|
||||
|
||||
// 发送通知
|
||||
return micUserChangeNotice(roomProfile);
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
ResponseAssert.isTrue(LiveMicErrorCode.MICROPHONE_OCCUPIED,false);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
// lock.unlock();
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
// P0: 不再吞掉所有异常,业务异常直接上抛保留原始错误码,记录日志便于排查
|
||||
log.error("上麦失败 roomId={}, micIndex={}, userId={}", roomId, micIndex, userId, e);
|
||||
throw e;
|
||||
} finally {
|
||||
micOpsUnlock(roomId, micIndex);
|
||||
}
|
||||
}
|
||||
@ -522,7 +533,6 @@ public class LiveMicrophoneGatewayImpl implements LiveMicrophoneGateway {
|
||||
}
|
||||
|
||||
Map<Integer, LiveMicrophone> liveMicrophoneMap = mapLiveMicrophone(roomId);
|
||||
log.info("在线取麦克风列表信息 -Map: {}", liveMicrophoneMap);
|
||||
return liveMicSettingSeats.stream().map(seat -> new LiveMicrophoneDTO()
|
||||
.setRoomId(roomId)
|
||||
.setMicIndex(seat.getMicIndex())
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user