From 1cdb060a8aa59b0979f7609db1781805528e76e7 Mon Sep 17 00:00:00 2001 From: xiangpei <xiangpei@timesnew.cn> Date: 星期三, 25 六月 2025 18:25:42 +0800 Subject: [PATCH] 视频评论数、收藏数通过mq、redis实现 --- framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoCommentServiceImpl.java | 147 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 144 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoCommentServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoCommentServiceImpl.java index f71a858..ca4e7af 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoCommentServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoCommentServiceImpl.java @@ -1,20 +1,39 @@ package cn.lili.modules.lmk.service.impl; +import cn.lili.cache.Cache; +import cn.lili.cache.CachePrefix; +import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; import cn.lili.common.sensitive.SensitiveWordsFilter; +import cn.lili.modules.lmk.constant.RedisKeyExpireConstant; +import cn.lili.modules.lmk.domain.entity.ThumbsUpRecord; +import cn.lili.modules.lmk.domain.form.ThumbsUpRecordForm; import cn.lili.modules.lmk.domain.vo.CollectTypeNumVO; import cn.lili.modules.lmk.enums.general.VideoCommentStatusEnum; +import cn.lili.modules.lmk.event.event.VideoCommentNumCacheEvent; +import cn.lili.modules.lmk.service.ThumbsUpRecordService; +import cn.lili.rocketmq.RocketmqSendCallbackBuilder; +import cn.lili.rocketmq.tags.CommentTagsEnum; +import cn.lili.rocketmq.tags.OrderTagsEnum; +import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.metadata.IPage; import cn.lili.modules.lmk.domain.entity.VideoComment; import cn.lili.modules.lmk.mapper.VideoCommentMapper; import cn.lili.modules.lmk.service.VideoCommentService; import cn.lili.base.Result; +import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; +import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import cn.lili.modules.lmk.domain.form.VideoCommentForm; import cn.lili.modules.lmk.domain.vo.VideoCommentVO; import cn.lili.modules.lmk.domain.query.VideoCommentQuery; +import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.common.MixAll; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import cn.lili.utils.PageUtil; @@ -24,6 +43,7 @@ import java.util.List; import java.util.Objects; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** @@ -37,6 +57,11 @@ public class VideoCommentServiceImpl extends ServiceImpl<VideoCommentMapper, VideoComment> implements VideoCommentService { private final VideoCommentMapper videoCommentMapper; + private final Cache cache; + private final ThumbsUpRecordService thumbsUpRecordService; + private final RocketMQTemplate rocketMQTemplate; + private final RocketmqCustomProperties rocketmqCustomProperties; + private final ApplicationEventPublisher eventPublisher; /** * 娣诲姞 @@ -58,13 +83,16 @@ } } VideoComment entity = VideoCommentForm.getEntityByForm(form, null); - entity.setStatus(VideoCommentStatusEnum.AUDITING.getValue()); - + entity.setStatus(VideoCommentStatusEnum.NORMAL.getValue()); + entity.setUserId(UserContext.getCurrentUserId()); AuthUser currentUser = UserContext.getCurrentUser(); entity.setUserNickname(currentUser.getNickName()); entity.setUserAvatar(currentUser.getFace()); - baseMapper.insert(entity); + // 鍒濆鍖杛edis涓瘎璁虹殑鐐硅禐鏁伴噺 + cache.put(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(entity.getId()), 0, RedisKeyExpireConstant.COMMENT_LIKE_NUM_EXPIRE, RedisKeyExpireConstant.EXPIRE_DAY); + // 澶勭悊瑙嗛璇勮鏁� + eventPublisher.publishEvent(new VideoCommentNumCacheEvent(this, entity.getVideoId())); return Result.ok("娣诲姞鎴愬姛").data(this.detail(entity.getId()).get("data")); } @@ -129,14 +157,21 @@ @Override public Result wxPage(VideoCommentQuery query) { + query.setUserId(UserContext.getCurrentUserId()); IPage<VideoCommentVO> page = PageUtil.getPage(query, VideoCommentVO.class); if (StringUtils.isNotBlank(query.getMasterCommentId())) { // 鍔犺浇瀛愯瘎璁虹殑鎯呭喌 baseMapper.replyCommentPage(page, query); + for (VideoCommentVO comment : page.getRecords()) { + comment.setThumbsUpNum(this.getCommentThumbsUpNum(comment.getId(), comment.getThumbsUpNum())); + } return Result.ok().data(page.getRecords()); } else { // 鍔犺浇涓昏瘎璁虹殑鎯呭喌銆備富璇勮id = masterCommentId baseMapper.masterCommentPage(page, query); + for (VideoCommentVO comment : page.getRecords()) { + comment.setThumbsUpNum(this.getCommentThumbsUpNum(comment.getId(), comment.getThumbsUpNum())); + } } return Result.ok().data(page.getRecords()).total(page.getTotal()); } @@ -146,4 +181,110 @@ public List<CollectTypeNumVO> countNumGroupByVideo() { return baseMapper.countNumGroupByVideo(); } + + @Override + public Result thumbsUp(ThumbsUpRecordForm form) { + ThumbsUpRecord record = ThumbsUpRecordForm.getEntityByForm(form, null); + record.setUserId(UserContext.getCurrentUserId()); + + // 璧癿q寮傛澶勭悊 + String destination = rocketmqCustomProperties.getCommentTopic() + ":" + CommentTagsEnum.THUMBS_UP.name(); + rocketMQTemplate.asyncSend(destination, JSON.toJSONString(record), RocketmqSendCallbackBuilder.commonCallback()); + return Result.ok(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void mqThumbsUp(ThumbsUpRecord record) { + boolean exists = new LambdaQueryChainWrapper<>(thumbsUpRecordService.getBaseMapper()) + .eq(ThumbsUpRecord::getRefId, record.getRefId()) + .eq(ThumbsUpRecord::getUserId, record.getUserId()) + .exists(); + if (exists) { + return; + } + thumbsUpRecordService.save(record); + VideoComment comment = this.getById(record.getRefId()); + if (cache.exist(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(record.getRefId()))) { + cache.incr(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(record.getRefId())); + } else { + if (Objects.nonNull(comment)) { + cache.put(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(comment.getId()), comment.getThumbsUpNum() + 1, RedisKeyExpireConstant.COMMENT_LIKE_NUM_EXPIRE, RedisKeyExpireConstant.EXPIRE_DAY); + } + } + // 鏍囪瘑璇ヨ瘎璁洪渶瑕侀�氳繃瀹氭椂浠诲姟缁熻鐐硅禐鏁� + if (Objects.nonNull(comment) && ! comment.getThumbsUpJob()) { + new LambdaUpdateChainWrapper<>(baseMapper) + .eq(VideoComment::getId, comment.getId()) + .set(VideoComment::getThumbsUpJob, Boolean.TRUE) + .update(); + } + } + + @Override + public Result cancelThumbsUp(ThumbsUpRecordForm form) { + ThumbsUpRecord record = ThumbsUpRecordForm.getEntityByForm(form, null); + record.setUserId(UserContext.getCurrentUserId()); + // 璧癿q寮傛澶勭悊 + String destination = rocketmqCustomProperties.getCommentTopic() + ":" + CommentTagsEnum.CANCEL_THUMBS_UP.name(); + rocketMQTemplate.asyncSend(destination, JSON.toJSONString(record), RocketmqSendCallbackBuilder.commonCallback()); + return Result.ok(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void mqCancelThumbsUp(ThumbsUpRecord record) { + new LambdaUpdateChainWrapper<>(thumbsUpRecordService.getBaseMapper()) + .eq(ThumbsUpRecord::getRefId, record.getRefId()) + .eq(ThumbsUpRecord::getThumbsUpType, record.getThumbsUpType()) + .eq(ThumbsUpRecord::getUserId, record.getUserId()) + .remove(); + // redis鏁伴噺鍑忎竴 + VideoComment comment = this.getById(record.getRefId()); + if (cache.exist(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(record.getRefId()))) { + cache.decr(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(record.getRefId())); + } else { + if (Objects.nonNull(comment)) { + cache.put(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(comment.getId()), comment.getThumbsUpNum() - 1, RedisKeyExpireConstant.COMMENT_LIKE_NUM_EXPIRE, RedisKeyExpireConstant.EXPIRE_DAY); + } + } + // 鏍囪瘑璇ヨ瘎璁洪渶瑕侀�氳繃瀹氭椂浠诲姟缁熻鐐硅禐鏁� + if (Objects.nonNull(comment) && ! comment.getThumbsUpJob()) { + new LambdaUpdateChainWrapper<>(baseMapper) + .eq(VideoComment::getId, comment.getId()) + .set(VideoComment::getThumbsUpJob, Boolean.TRUE) + .update(); + } + } + + /** + * 浠巖edis涓幏鍙栬瘎璁虹偣璧炴暟閲忥紝濡傛灉redis涓病鏈夊垯灏唌ysql涓殑鏁伴噺鍐欏叆鍒皉edis + * + * @param commentId + * @param mysqlNum + * @return + */ + private Integer getCommentThumbsUpNum(String commentId, Integer mysqlNum) { + Object redisNum = cache.get(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(commentId)); + if (Objects.isNull(redisNum)) { + // redis涓病鏈夊氨鎶婃暟鎹簱鐨勫啓鍒皉edis涓� + cache.put(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(commentId), mysqlNum, RedisKeyExpireConstant.COMMENT_LIKE_NUM_EXPIRE, RedisKeyExpireConstant.EXPIRE_DAY); + return mysqlNum; + } + return (Integer) redisNum; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateCommentThumbsUpNumBatch(List<CollectTypeNumVO> numList) { + // 鎸�500鏉℃暟鎹繘琛屾媶鍒� + List<List<CollectTypeNumVO>> chunks = ListUtils.partition(numList, 500); + for (List<CollectTypeNumVO> chunk : chunks) { + baseMapper.updateCommentThumbsUpNumBatch(chunk); + new LambdaUpdateChainWrapper<>(baseMapper) + .in(VideoComment::getId, chunk.stream().map(CollectTypeNumVO::getId).collect(Collectors.toList())) + .set(VideoComment::getThumbsUpJob, Boolean.FALSE) + .update(); + } + } } -- Gitblit v1.8.0