diff --git a/nacos_config/rc-service-other/application.yml b/nacos_config/rc-service-other/application.yml index d0967b5c..c28f32d8 100644 --- a/nacos_config/rc-service-other/application.yml +++ b/nacos_config/rc-service-other/application.yml @@ -128,6 +128,13 @@ task: topic: ${TASK_CENTER_EVENT_MQ_TOPIC:RC_DEFAULT_APP_ORDINARY} tag: ${TASK_CENTER_EVENT_MQ_TAG:task_center_event} +cp: + relation-broadcast: + mq: + enabled: ${CP_RELATION_BROADCAST_MQ_ENABLED:false} + topic: ${CP_RELATION_BROADCAST_MQ_TOPIC:RC_DEFAULT_APP_ORDINARY} + tag: ${CP_RELATION_BROADCAST_MQ_TAG:cp_relation_broadcast} + voice-room: region-broadcast: go: diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/ProcessCpApplyCmd.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/ProcessCpApplyCmd.java index 8a54645d..052ec829 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/ProcessCpApplyCmd.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/ProcessCpApplyCmd.java @@ -4,9 +4,10 @@ import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; import com.red.circle.external.inner.endpoint.message.ImMessageClient; import com.red.circle.framework.core.asserts.ResponseAssert; import com.red.circle.framework.core.response.CommonErrorCode; -import com.red.circle.mq.business.model.event.user.CpApplyEvent; -import com.red.circle.mq.rocket.business.producer.UserMqMessageService; -import com.red.circle.other.app.dto.cmd.user.relation.cp.ProcessApplyCmd; +import com.red.circle.mq.business.model.event.user.CpApplyEvent; +import com.red.circle.mq.rocket.business.producer.UserMqMessageService; +import com.red.circle.other.app.common.cp.CpRelationBroadcastMqClient; +import com.red.circle.other.app.dto.cmd.user.relation.cp.ProcessApplyCmd; import com.red.circle.other.domain.gateway.user.UserProfileGateway; import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService; import com.red.circle.other.infra.database.rds.entity.user.user.CpApply; @@ -47,9 +48,10 @@ public class ProcessCpApplyCmd { private final ImMessageClient imMessageClient; private final WalletGoldClient walletGoldClient; private final UserMqMessageService userMqMessageService; - private final CpRelationshipService cpRelationshipService; - private final UserProfileGateway userProfileGateway; - private final CpRelationshipCacheService cpRelationshipCacheService; + private final CpRelationshipService cpRelationshipService; + private final UserProfileGateway userProfileGateway; + private final CpRelationshipCacheService cpRelationshipCacheService; + private final CpRelationBroadcastMqClient cpRelationBroadcastMqClient; public void execute(ProcessApplyCmd cmd) { process(cmd); @@ -106,6 +108,8 @@ public class ProcessCpApplyCmd { refuseStatusWaitIfLimitReached(cmd, cpApply, relationType); cpRelationshipCacheService.remove(Arrays.asList(cpApply.getSendApplyUserId(), cpApply.getAcceptApplyUserId())); + cpRelationBroadcastMqClient.publish(cmd.requireReqSysOrigin(), cpApply.getId(), + cpApply.getSendApplyUserId(), cpApply.getAcceptApplyUserId(), relationType); } private void refuseStatusWaitIfLimitReached(ProcessApplyCmd cmd, CpApply cpApply, diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/cp/CpRelationBroadcastMqClient.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/cp/CpRelationBroadcastMqClient.java new file mode 100644 index 00000000..6cc1f0cd --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/cp/CpRelationBroadcastMqClient.java @@ -0,0 +1,147 @@ +package com.red.circle.other.app.common.cp; + +import com.red.circle.component.mq.MessageEvent; +import com.red.circle.mq.rocket.business.service.MessageSenderService; +import com.red.circle.other.domain.gateway.user.UserProfileGateway; +import com.red.circle.other.domain.model.user.UserProfile; +import com.red.circle.other.infra.enums.user.user.CpRelationshipType; +import java.time.Instant; +import java.util.Objects; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@RequiredArgsConstructor +public class CpRelationBroadcastMqClient { + + private final ObjectProvider messageSenderServiceProvider; + private final UserProfileGateway userProfileGateway; + + @Value("${cp.relation-broadcast.mq.enabled:false}") + private boolean mqEnabled; + + @Value("${cp.relation-broadcast.mq.topic:RC_DEFAULT_APP_ORDINARY}") + private String mqTopic; + + @Value("${cp.relation-broadcast.mq.tag:cp_relation_broadcast}") + private String mqTag; + + public void publish(String sysOrigin, Long applyId, Long userId, Long cpUserId, String relationType) { + if (!mqEnabled) { + return; + } + if (Objects.isNull(userId) || Objects.isNull(cpUserId)) { + log.warn("CP relation broadcast mq skip: user id missing. applyId={}, userId={}, cpUserId={}", + applyId, userId, cpUserId); + return; + } + + String normalizedRelationType = CpRelationshipType.normalize(relationType); + String eventId = buildEventId(applyId, userId, cpUserId, normalizedRelationType); + CpRelationBroadcastEvent event = new CpRelationBroadcastEvent() + .setSysOrigin(defaultIfBlank(sysOrigin, "LIKEI")) + .setEventId(eventId) + .setApplyId(applyId) + .setRelationType(normalizedRelationType) + .setUserId(userId) + .setCpUserId(cpUserId) + .setSendUserId(userId) + .setAcceptUserId(cpUserId) + .setOccurredAt(Instant.now().toString()) + .setUser(loadUser(userId)) + .setCpUser(loadUser(cpUserId)); + + try { + MessageSenderService senderService = messageSenderServiceProvider.getIfAvailable(); + if (Objects.isNull(senderService)) { + log.warn("CP relation broadcast mq sender missing, skip. eventId={}", eventId); + return; + } + senderService.sendEventMessage(MessageEvent.builder() + .consumeId(eventId) + .topicString(defaultIfBlank(mqTopic, "RC_DEFAULT_APP_ORDINARY")) + .tag(defaultIfBlank(mqTag, "cp_relation_broadcast")) + .body(event) + .build()); + } catch (Exception e) { + log.warn("CP relation broadcast mq publish error. eventId={}", eventId, e); + } + } + + private CpRelationUser loadUser(Long userId) { + CpRelationUser fallback = new CpRelationUser() + .setId(userId) + .setUserId(userId) + .setAccount(Objects.toString(userId, "")) + .setUserNickname(Objects.toString(userId, "")); + try { + UserProfile profile = userProfileGateway.getByUserId(userId); + if (Objects.isNull(profile)) { + return fallback; + } + return new CpRelationUser() + .setId(profile.getId()) + .setUserId(profile.getId()) + .setAccount(defaultIfBlank(profile.getAccount(), fallback.getAccount())) + .setUserNickname(defaultIfBlank(profile.getUserNickname(), fallback.getUserNickname())) + .setNickname(defaultIfBlank(profile.getUserNickname(), fallback.getUserNickname())) + .setUserAvatar(profile.getUserAvatar()) + .setAvatar(profile.getUserAvatar()) + .setCountryCode(profile.getCountryCode()) + .setCountryName(profile.getCountryName()) + .setOriginSys(profile.getOriginSys()); + } catch (Exception e) { + log.warn("CP relation broadcast load user profile failed. userId={}", userId, e); + return fallback; + } + } + + private String buildEventId(Long applyId, Long userId, Long cpUserId, String relationType) { + if (Objects.nonNull(applyId)) { + return "CP_RELATION:" + relationType + ":" + applyId; + } + return "CP_RELATION:" + relationType + ":" + userId + ":" + cpUserId; + } + + private String defaultIfBlank(String value, String fallback) { + String normalized = Objects.toString(value, "").trim(); + return normalized.isEmpty() ? fallback : normalized; + } + + @Data + @Accessors(chain = true) + private static class CpRelationBroadcastEvent { + private String sysOrigin; + private String eventId; + private Long applyId; + private String relationType; + private Long userId; + private Long cpUserId; + private Long sendUserId; + private Long acceptUserId; + private String occurredAt; + private CpRelationUser user; + private CpRelationUser cpUser; + } + + @Data + @Accessors(chain = true) + private static class CpRelationUser { + private Long id; + private Long userId; + private String account; + private String nickname; + private String userNickname; + private String avatar; + private String userAvatar; + private String countryCode; + private String countryName; + private String originSys; + } +}