From d15ea98dc6e575a27a545e2dc0ffddddffb77b09 Mon Sep 17 00:00:00 2001 From: hy001 Date: Thu, 16 Apr 2026 16:22:51 +0800 Subject: [PATCH] fix live mic token flow and idempotent go-up --- .../adapter/app/imtrtc/ImRestController.java | 56 ++++++----- .../app/command/mic/LiveMicGoUpCmdExe.java | 47 +++++---- .../repository/LiveMicrophoneGatewayImpl.java | 99 +++++++++++-------- 3 files changed, 111 insertions(+), 91 deletions(-) diff --git a/rc-service/rc-service-external/external-adapter/src/main/java/com/red/circle/external/adapter/app/imtrtc/ImRestController.java b/rc-service/rc-service-external/external-adapter/src/main/java/com/red/circle/external/adapter/app/imtrtc/ImRestController.java index 42e3af7..3ce1a84 100644 --- a/rc-service/rc-service-external/external-adapter/src/main/java/com/red/circle/external/adapter/app/imtrtc/ImRestController.java +++ b/rc-service/rc-service-external/external-adapter/src/main/java/com/red/circle/external/adapter/app/imtrtc/ImRestController.java @@ -281,33 +281,35 @@ public class ImRestController extends BaseController { } - /** - * 获取上麦token - * - * @param channelName - * @param userId - * @return - */ - public String createChannelSubscriberToken(String channelName, Long userId) { - RtcTokenBuilder2 var3 = new RtcTokenBuilder2(); - String token = var3.buildTokenWithUid(appId, certificate, channelName, Integer.parseInt(getAccount(userId)), RtcTokenBuilder2.Role.ROLE_SUBSCRIBER, 21600, 21600); - userAgoraTokenCacheService.save(token, userId, Long.valueOf(channelName)); - return token; - } - - /** - * 获取房间token - * - * @param channelName - * @param userId - * @return - */ - public String createChannelPublisherToken(String channelName, Long userId) { - RtcTokenBuilder2 var3 = new RtcTokenBuilder2(); - String token = var3.buildTokenWithUid(appId, certificate, channelName, Integer.parseInt(getAccount(userId)), RtcTokenBuilder2.Role.ROLE_PUBLISHER, 21600, 21600); - userAgoraTokenCacheService.saveRoom(token, userId, Long.valueOf(channelName)); - return token; - } + /** + * 获取观众token + * + * @param channelName + * @param userId + * @return + */ + public String createChannelSubscriberToken(String channelName, Long userId) { + RtcTokenBuilder2 var3 = new RtcTokenBuilder2(); + String token = var3.buildTokenWithUid(appId, certificate, channelName, Integer.parseInt(getAccount(userId)), RtcTokenBuilder2.Role.ROLE_SUBSCRIBER, 21600, 21600); + userAgoraTokenCacheService.removeRoom(userId, Long.valueOf(channelName)); + userAgoraTokenCacheService.saveRoom(token, userId, Long.valueOf(channelName)); + return token; + } + + /** + * 获取上麦token + * + * @param channelName + * @param userId + * @return + */ + public String createChannelPublisherToken(String channelName, Long userId) { + RtcTokenBuilder2 var3 = new RtcTokenBuilder2(); + String token = var3.buildTokenWithUid(appId, certificate, channelName, Integer.parseInt(getAccount(userId)), RtcTokenBuilder2.Role.ROLE_PUBLISHER, 21600, 21600); + userAgoraTokenCacheService.remove(userId, Long.valueOf(channelName)); + userAgoraTokenCacheService.save(token, userId, Long.valueOf(channelName)); + return token; + } /** * 根据用户id获取用户account diff --git a/rc-service/rc-service-live/live-application/src/main/java/com/red/circle/live/app/command/mic/LiveMicGoUpCmdExe.java b/rc-service/rc-service-live/live-application/src/main/java/com/red/circle/live/app/command/mic/LiveMicGoUpCmdExe.java index d763c5e..f8fa717 100644 --- a/rc-service/rc-service-live/live-application/src/main/java/com/red/circle/live/app/command/mic/LiveMicGoUpCmdExe.java +++ b/rc-service/rc-service-live/live-application/src/main/java/com/red/circle/live/app/command/mic/LiveMicGoUpCmdExe.java @@ -1,10 +1,11 @@ package com.red.circle.live.app.command.mic; import com.red.circle.component.redis.service.RedisService; -import com.red.circle.external.inner.endpoint.message.TrtcClient; -import com.red.circle.framework.core.asserts.ResponseAssert; -import com.red.circle.live.app.convertor.LiveMicAppConvertor; -import com.red.circle.live.app.dto.clientobject.LiveMicrophoneCO; +import com.red.circle.external.inner.endpoint.message.TrtcClient; +import com.red.circle.framework.core.asserts.ResponseAssert; +import com.red.circle.framework.core.response.CommonErrorCode; +import com.red.circle.live.app.convertor.LiveMicAppConvertor; +import com.red.circle.live.app.dto.clientobject.LiveMicrophoneCO; import com.red.circle.live.app.dto.cmd.MicUpDownCmd; import com.red.circle.live.domain.gateway.LiveMicrophoneGateway; import com.red.circle.live.domain.live.dto.LiveMicrophoneNoticeDTO; @@ -53,27 +54,31 @@ public class LiveMicGoUpCmdExe { public LiveMicrophoneCO execute(MicUpDownCmd cmd) { checkPermissions(cmd); - LiveMicrophoneNoticeDTO noticeDTO = liveMicrophoneGateway.goUp( - cmd.getRoomId(), - cmd.getMickIndex(), - cmd.requiredReqUserId() - ); - LiveMicrophoneCO notice = returnMicrophoneCO(cmd, noticeDTO); - String roomToken = userAgoraTokenCacheService.getUserAgoraToken(cmd.getReqUserId(), cmd.getRoomId()); - if (Objects.isNull(roomToken)) { - notice.setRoomToken(trtcClient.createAgoraTokenGoUp(cmd.getReqUserId(), cmd.getRoomId().toString()).getBody()); - //notice.setRoomToken(trtcClient.createAgoraTokenGoUp(cmd.getReqUserId(),cmd.getRoomId().toString()).getBody()); - userAgoraTokenCacheService.save(notice.getRoomToken(), cmd.getReqUserId(), cmd.getRoomId()); - } else { - notice.setRoomToken(roomToken); - } - //notice.setRoomToken(createAgoraTokenGoUp(cmd)); + LiveMicrophoneNoticeDTO noticeDTO = liveMicrophoneGateway.goUp( + cmd.getRoomId(), + cmd.getMickIndex(), + cmd.requiredReqUserId() + ); + LiveMicrophoneCO notice = returnMicrophoneCO(cmd, noticeDTO); + notice.setRoomToken(refreshPublisherToken(cmd)); + //notice.setRoomToken(createAgoraTokenGoUp(cmd)); // 房主邀请成员上麦 handleRoomDailyTask(cmd); - return notice; - } + return notice; + } + + private String refreshPublisherToken(MicUpDownCmd cmd) { + String roomToken = trtcClient.createAgoraTokenGoUp( + cmd.getReqUserId(), + cmd.getRoomId().toString() + ).getBody(); + ResponseAssert.notNull(CommonErrorCode.THIRD_PARTY_SERVER_ERROR, roomToken); + userAgoraTokenCacheService.remove(cmd.getReqUserId(), cmd.getRoomId()); + userAgoraTokenCacheService.save(roomToken, cmd.getReqUserId(), cmd.getRoomId()); + return roomToken; + } private void handleRoomDailyTask(MicUpDownCmd cmd) { try { diff --git a/rc-service/rc-service-live/live-infrastructure/src/main/java/com/red/circle/live/infra/repository/LiveMicrophoneGatewayImpl.java b/rc-service/rc-service-live/live-infrastructure/src/main/java/com/red/circle/live/infra/repository/LiveMicrophoneGatewayImpl.java index eebeebd..7ae23b0 100644 --- a/rc-service/rc-service-live/live-infrastructure/src/main/java/com/red/circle/live/infra/repository/LiveMicrophoneGatewayImpl.java +++ b/rc-service/rc-service-live/live-infrastructure/src/main/java/com/red/circle/live/infra/repository/LiveMicrophoneGatewayImpl.java @@ -159,49 +159,62 @@ public class LiveMicrophoneGatewayImpl implements LiveMicrophoneGateway { .collect(Collectors.toMap(LiveMicUser::getId, v -> v)); } - @Override - public LiveMicrophoneNoticeDTO goUp(Long roomId, Integer micIndex, Long userId) { - micOpsLock(roomId, micIndex); -// RLock lock = redissonClient.getLock(roomId.toString()+micIndex.toString()+"room"); -// lock.lock(); - 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()); - checkMicAvailableUse(roomId, micIndex); - // 下掉已上麦克风 - List lives = liveMicCacheService.listLiveMicrophone(roomId, userId); - if (CollectionUtils.isNotEmpty(lives)) { - liveMicCacheService.goDown(roomId, - lives.stream().map(LiveMicrophone::getMicIndex).toList()); - } - - // 上麦克风 - liveMicCacheService.goUp(roomId, micIndex, liveMicrophone); - - // 清理活跃用户 - liveMicCacheService.refreshNotActiveUser(roomId); - - // 发送通知 - return micUserChangeNotice(roomProfile); - }catch (Exception e){ - e.printStackTrace(); - ResponseAssert.isTrue(LiveMicErrorCode.MICROPHONE_OCCUPIED,false); - return null; - } - finally { -// lock.unlock(); - micOpsUnlock(roomId, micIndex); - } - } + @Override + public LiveMicrophoneNoticeDTO goUp(Long roomId, Integer micIndex, Long userId) { + micOpsLock(roomId, micIndex); +// RLock lock = redissonClient.getLock(roomId.toString()+micIndex.toString()+"room"); +// lock.lock(); + 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); + ResponseAssert.notNull(LiveMicErrorCode.MIC_INDEX_NOT_FOUND, liveMicrophone); + ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, liveMicrophone.getUser()); + + if (liveMicCacheService.checkEqSelf(roomId, micIndex, userId)) { + liveMicCacheService.refreshNotActiveUser(roomId); + return micUserChangeNotice(roomProfile); + } + + checkMicAvailableUse(roomId, micIndex); + liveMicrophone.getUser().setCharmLevel( + userLevelClient.getUserLevel( + SysOriginPlatformEnum.valueOf(roomProfile.getSysOrigin()), + userId + ).getBody().getCharmLevel() + ); + + // 下掉已上麦克风 + List lives = liveMicCacheService.listLiveMicrophone(roomId, userId); + if (CollectionUtils.isNotEmpty(lives)) { + List goDownMicIndex = lives.stream() + .map(LiveMicrophone::getMicIndex) + .filter(index -> !Objects.equals(index, micIndex)) + .toList(); + if (CollectionUtils.isNotEmpty(goDownMicIndex)) { + liveMicCacheService.goDown(roomId, goDownMicIndex); + } + } + + // 上麦克风 + liveMicCacheService.goUp(roomId, micIndex, liveMicrophone); + + // 清理活跃用户 + liveMicCacheService.refreshNotActiveUser(roomId); + + // 发送通知 + return micUserChangeNotice(roomProfile); + } finally { +// lock.unlock(); + micOpsUnlock(roomId, micIndex); + } + } @Override public void goDown(Long roomId, Integer micIndex, Long userId) {