feat(count): 实现关注与粉丝数统计功能
- 新增关注数与粉丝数 MQ 消费者 - 在用户关系服务中新增关注/取关时发送 MQ 消息逻辑 - 新增关注/取关类型枚举类 - 新增用于统计的 MQ 常量定义 - 调整应用主类包路径以符合项目结构(致命,查半天) - 移除配置文件中不再使用的 MQ 消费者限流配置项
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
package com.hanserwei.hannote.count.biz.domain;
|
||||
package com.hanserwei.hannote.count.biz;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.hanserwei.hannote.count.biz.constant;
|
||||
|
||||
public interface MQConstants {
|
||||
|
||||
/**
|
||||
* Topic: 关注数计数
|
||||
*/
|
||||
String TOPIC_COUNT_FOLLOWING = "CountFollowingTopic";
|
||||
|
||||
/**
|
||||
* Topic: 粉丝数计数
|
||||
*/
|
||||
String TOPIC_COUNT_FANS = "CountFansTopic";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.hanserwei.hannote.count.biz.consumer;
|
||||
|
||||
import com.hanserwei.hannote.count.biz.constant.MQConstants;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
consumerGroup = "han_note_group_" + MQConstants.TOPIC_COUNT_FANS,
|
||||
topic = MQConstants.TOPIC_COUNT_FANS
|
||||
)
|
||||
@Slf4j
|
||||
public class CountFansConsumer implements RocketMQListener<String> {
|
||||
@Override
|
||||
public void onMessage(String body) {
|
||||
log.info("## 消费了 MQ [计数:粉丝数]: {}", body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.hanserwei.hannote.count.biz.consumer;
|
||||
|
||||
import com.hanserwei.hannote.count.biz.constant.MQConstants;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
consumerGroup = "han_note_group_" + MQConstants.TOPIC_COUNT_FOLLOWING,
|
||||
topic = MQConstants.TOPIC_COUNT_FOLLOWING
|
||||
)
|
||||
@Slf4j
|
||||
public class CountFollowingConsumer implements RocketMQListener<String> {
|
||||
@Override
|
||||
public void onMessage(String body) {
|
||||
log.info("## 消费了 MQ [计数:关注数]: {}", body);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,3 @@ mybatis-plus:
|
||||
global-config:
|
||||
banner: false
|
||||
mapper-locations: classpath*:/mapperxml/*.xml
|
||||
mq-consumer: # MQ 消费者
|
||||
follow-unfollow: # 关注、取关
|
||||
rate-limit: 5000 # 每秒限流阈值
|
||||
@@ -16,4 +16,14 @@ public interface MQConstants {
|
||||
* 取关标签
|
||||
*/
|
||||
String TAG_UNFOLLOW = "Unfollow";
|
||||
|
||||
/**
|
||||
* Topic: 关注数计数
|
||||
*/
|
||||
String TOPIC_COUNT_FOLLOWING = "CountFollowingTopic";
|
||||
|
||||
/**
|
||||
* Topic: 粉丝数计数
|
||||
*/
|
||||
String TOPIC_COUNT_FANS = "CountFansTopic";
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import com.hanserwei.hannote.user.relation.biz.constant.MQConstants;
|
||||
import com.hanserwei.hannote.user.relation.biz.constant.RedisKeyConstants;
|
||||
import com.hanserwei.hannote.user.relation.biz.domain.dataobject.FansDO;
|
||||
import com.hanserwei.hannote.user.relation.biz.domain.dataobject.FollowingDO;
|
||||
import com.hanserwei.hannote.user.relation.biz.enums.FollowUnfollowTypeEnum;
|
||||
import com.hanserwei.hannote.user.relation.biz.model.dto.CountFollowUnfollowMqDTO;
|
||||
import com.hanserwei.hannote.user.relation.biz.model.dto.FollowUserMqDTO;
|
||||
import com.hanserwei.hannote.user.relation.biz.model.dto.UnfollowUserMqDTO;
|
||||
import com.hanserwei.hannote.user.relation.biz.service.FansDOService;
|
||||
@@ -15,13 +17,17 @@ import com.hanserwei.hannote.user.relation.biz.util.DateUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.client.producer.SendCallback;
|
||||
import org.apache.rocketmq.client.producer.SendResult;
|
||||
import org.apache.rocketmq.common.message.Message;
|
||||
import org.apache.rocketmq.spring.annotation.ConsumeMode;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.scripting.support.ResourceScriptSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
@@ -32,8 +38,8 @@ import java.util.Objects;
|
||||
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
consumerGroup = "han_note_group_" + MQConstants.TOPIC_FOLLOW_OR_UNFOLLOW,
|
||||
topic = MQConstants.TOPIC_FOLLOW_OR_UNFOLLOW,
|
||||
consumerGroup = "han_note_group_" + MQConstants.TOPIC_FOLLOW_OR_UNFOLLOW, //han_note_group_FollowUnfollowTopic
|
||||
topic = MQConstants.TOPIC_FOLLOW_OR_UNFOLLOW, //FollowUnfollowTopic
|
||||
consumeMode = ConsumeMode.ORDERLY
|
||||
)
|
||||
@Slf4j
|
||||
@@ -47,6 +53,8 @@ public class FollowUnfollowConsumer implements RocketMQListener<Message> {
|
||||
private RateLimiter rateLimiter;
|
||||
@Resource
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
@Resource
|
||||
private RocketMQTemplate rocketMQTemplate;
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
@@ -114,6 +122,17 @@ public class FollowUnfollowConsumer implements RocketMQListener<Message> {
|
||||
String fansRedisKey = RedisKeyConstants.buildUserFansKey(unfollowUserId);
|
||||
// 删除指定粉丝
|
||||
redisTemplate.opsForZSet().remove(fansRedisKey, userId);
|
||||
|
||||
// 发送MQ消息通知计数服务,统计关注数
|
||||
// 构建DTO对象
|
||||
CountFollowUnfollowMqDTO countFollowUnfollowMqDTO = CountFollowUnfollowMqDTO.builder()
|
||||
.userId(userId)
|
||||
.targetUserId(unfollowUserId)
|
||||
.type(FollowUnfollowTypeEnum.UNFOLLOW.getCode())
|
||||
.build();
|
||||
|
||||
// 发送MQ
|
||||
sendMQ(countFollowUnfollowMqDTO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +196,53 @@ public class FollowUnfollowConsumer implements RocketMQListener<Message> {
|
||||
|
||||
// 执行Lua脚本
|
||||
redisTemplate.execute(script, Collections.singletonList(fansZSetKey), userId, timestamp);
|
||||
|
||||
// 发送MQ消息通知计数服务,统计关注数
|
||||
// 构建消息体
|
||||
CountFollowUnfollowMqDTO countFollowUnfollowMqDTO = CountFollowUnfollowMqDTO.builder()
|
||||
.userId(userId)
|
||||
.targetUserId(followUserId)
|
||||
.type(FollowUnfollowTypeEnum.FOLLOW.getCode())
|
||||
.build();
|
||||
|
||||
sendMQ(countFollowUnfollowMqDTO);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送MQ消息
|
||||
*
|
||||
* @param countFollowUnfollowMqDTO 消息体
|
||||
*/
|
||||
private void sendMQ(CountFollowUnfollowMqDTO countFollowUnfollowMqDTO) {
|
||||
// 构建MQ消息体
|
||||
org.springframework.messaging.Message<String> message = MessageBuilder.withPayload(JsonUtils.toJsonString(countFollowUnfollowMqDTO))
|
||||
.build();
|
||||
|
||||
// 异步发送 MQ 消息
|
||||
rocketMQTemplate.asyncSend(MQConstants.TOPIC_COUNT_FOLLOWING, message, new SendCallback() {
|
||||
@Override
|
||||
public void onSuccess(SendResult sendResult) {
|
||||
log.info("==> 【计数服务:关注数】MQ 发送成功,SendResult: {}", sendResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(Throwable throwable) {
|
||||
log.error("==> 【计数服务:关注数】MQ 发送异常: ", throwable);
|
||||
}
|
||||
});
|
||||
|
||||
// 发送 MQ 通知计数服务:统计粉丝数
|
||||
rocketMQTemplate.asyncSend(MQConstants.TOPIC_COUNT_FANS, message, new SendCallback() {
|
||||
@Override
|
||||
public void onSuccess(SendResult sendResult) {
|
||||
log.info("==> 【计数服务:粉丝数】MQ 发送成功,SendResult: {}", sendResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(Throwable throwable) {
|
||||
log.error("==> 【计数服务:粉丝数】MQ 发送异常: ", throwable);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.hanserwei.hannote.user.relation.biz.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum FollowUnfollowTypeEnum {
|
||||
// 关注
|
||||
FOLLOW(1),
|
||||
// 取关
|
||||
UNFOLLOW(0),
|
||||
;
|
||||
|
||||
private final Integer code;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.hanserwei.hannote.user.relation.biz.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class CountFollowUnfollowMqDTO {
|
||||
|
||||
/**
|
||||
* 原用户
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 目标用户
|
||||
*/
|
||||
private Long targetUserId;
|
||||
|
||||
/**
|
||||
* 1:关注 0:取关
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user