You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
6.0 KiB
235 lines
6.0 KiB
2 months ago
|
package comment_service
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"strconv"
|
||
|
"time"
|
||
|
|
||
|
misc "github.com/TremblingV5/DouTok/applications/comment/infra/misc"
|
||
|
"github.com/TremblingV5/box/dbtx"
|
||
|
|
||
|
"github.com/TremblingV5/DouTok/applications/comment/domain/entity/comment"
|
||
|
"github.com/TremblingV5/DouTok/applications/comment/domain/entity/comment_count"
|
||
|
"github.com/TremblingV5/DouTok/applications/comment/infra/repository/comment_count_repo"
|
||
|
"github.com/TremblingV5/DouTok/applications/comment/infra/repository/comment_hb_repo"
|
||
|
"github.com/TremblingV5/DouTok/applications/comment/infra/repository/comment_repo"
|
||
|
"github.com/TremblingV5/DouTok/pkg/cache"
|
||
|
"github.com/TremblingV5/DouTok/pkg/errno"
|
||
|
"github.com/go-redis/redis/v8"
|
||
|
|
||
|
"github.com/TremblingV5/DouTok/pkg/utils"
|
||
|
)
|
||
|
|
||
|
type Service struct {
|
||
|
commentCountCache *cache.CountMapCache
|
||
|
commentTotalCountCache *cache.CountMapCache
|
||
|
commentHBRepository comment_hb_repo.Repository
|
||
|
commentCountRedis *redis.Client
|
||
|
commentTotalCountRedis *redis.Client
|
||
|
commentRepository comment_repo.Repository
|
||
|
commentCountRepository comment_count_repo.Repository
|
||
|
}
|
||
|
|
||
|
func New(
|
||
|
commentCountCache *cache.CountMapCache,
|
||
|
commentTotalCountCache *cache.CountMapCache,
|
||
|
commentHBRepository comment_hb_repo.Repository,
|
||
|
commentCountRedis *redis.Client,
|
||
|
commentTotalCountRedis *redis.Client,
|
||
|
) *Service {
|
||
|
return &Service{
|
||
|
commentCountCache: commentCountCache,
|
||
|
commentTotalCountCache: commentTotalCountCache,
|
||
|
commentHBRepository: commentHBRepository,
|
||
|
commentCountRedis: commentCountRedis,
|
||
|
commentTotalCountRedis: commentTotalCountRedis,
|
||
|
commentRepository: comment_repo.New(),
|
||
|
commentCountRepository: comment_count_repo.New(),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *Service) AddComment(
|
||
|
ctx context.Context,
|
||
|
videoId int64, userId int64, conId int64,
|
||
|
lastId int64, toUserId int64, content string,
|
||
|
) (c *comment.Entity, err error) {
|
||
|
ctx, persist := dbtx.WithTXPersist(ctx)
|
||
|
defer func() {
|
||
|
persist(err)
|
||
|
}()
|
||
|
|
||
|
timestamp := fmt.Sprint(time.Now().Unix())
|
||
|
|
||
|
id := utils.GetSnowFlakeId().Int64()
|
||
|
|
||
|
comment, err := comment.New(
|
||
|
comment.WithId(id),
|
||
|
comment.WithVideoId(videoId),
|
||
|
comment.WithUserId(userId),
|
||
|
comment.WithConversationId(conId),
|
||
|
comment.WithLastId(lastId),
|
||
|
comment.WithToUserId(toUserId),
|
||
|
comment.WithContent(content),
|
||
|
comment.WithTimestamp(timestamp),
|
||
|
)
|
||
|
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if err := s.commentRepository.Save(ctx, comment.ToModel()); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
// TODO: 通过消息队列异步写
|
||
|
if err := s.commentHBRepository.Save(ctx, comment.ToHBModel()); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
s.updateCacheComCount(videoId, true)
|
||
|
|
||
|
return comment, nil
|
||
|
}
|
||
|
|
||
|
func (s *Service) CountComment(ctx context.Context, videoId ...int64) (result map[int64]int64, e *errno.ErrNo, err error) {
|
||
|
ctx, persist := dbtx.WithTXPersist(ctx)
|
||
|
defer func() {
|
||
|
persist(err)
|
||
|
}()
|
||
|
|
||
|
resMap := make(map[int64]int64)
|
||
|
|
||
|
// 1. 从内存中查找喜欢数
|
||
|
var findAgain []int64
|
||
|
for _, v := range videoId {
|
||
|
cnt, ok := s.readComTotalCount(v)
|
||
|
|
||
|
if !ok {
|
||
|
findAgain = append(findAgain, v)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
resMap[v] = cnt
|
||
|
}
|
||
|
|
||
|
// 2. 从Redis中查找喜欢数
|
||
|
var findAgainAgain []int64
|
||
|
for _, v := range findAgain {
|
||
|
cnt, ok, _ := s.readComTotalCountFromCache(fmt.Sprint(v))
|
||
|
|
||
|
if !ok {
|
||
|
findAgainAgain = append(findAgainAgain, v)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
resMap[v] = cnt
|
||
|
s.commentTotalCountCache.Set(v, cnt)
|
||
|
}
|
||
|
|
||
|
// 3. 从MySQL中查找喜欢数
|
||
|
commentCountModels, err := s.commentCountRepository.LoadByIdList(ctx, findAgainAgain...)
|
||
|
if err != nil {
|
||
|
return nil, &misc.QueryCommentCountErr, err
|
||
|
}
|
||
|
|
||
|
commentCounts := comment_count.NewListFromModels(commentCountModels)
|
||
|
for _, v := range commentCounts {
|
||
|
resMap[v.Id] = v.Number
|
||
|
}
|
||
|
|
||
|
// 4. 如果仍然没有查找到该记录,则置0
|
||
|
for _, v := range videoId {
|
||
|
if _, ok := resMap[v]; !ok {
|
||
|
resMap[v] = 0
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return resMap, &misc.Success, nil
|
||
|
}
|
||
|
|
||
|
func (s *Service) readComTotalCount(videoId int64) (int64, bool) {
|
||
|
return s.commentTotalCountCache.Get(videoId)
|
||
|
}
|
||
|
|
||
|
func (s *Service) readComTotalCountFromCache(videoId string) (int64, bool, error) {
|
||
|
data, err := s.commentTotalCountRedis.Get(context.Background(), videoId).Result()
|
||
|
if errors.Is(err, redis.Nil) {
|
||
|
return 0, false, nil
|
||
|
} else if err != nil {
|
||
|
return 0, false, err
|
||
|
}
|
||
|
|
||
|
num, _ := strconv.ParseInt(data, 10, 64)
|
||
|
|
||
|
return num, true, nil
|
||
|
}
|
||
|
|
||
|
func (s *Service) updateCacheComCount(videoId int64, isAdd bool) {
|
||
|
if isAdd {
|
||
|
s.commentCountCache.Add(videoId, 1)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
s.commentCountCache.Add(videoId, -1)
|
||
|
}
|
||
|
|
||
|
func (s *Service) ListComment(ctx context.Context, videoId int64) (comment.List, errno.ErrNo, error) {
|
||
|
commentHBModels, err := s.commentHBRepository.ScanByPrefix(ctx, videoId)
|
||
|
if err != nil {
|
||
|
return nil, misc.QueryCommentListInHBErr, err
|
||
|
}
|
||
|
|
||
|
commentList := comment.NewListFromHBModels(commentHBModels)
|
||
|
return commentList, misc.Success, nil
|
||
|
}
|
||
|
|
||
|
func (s *Service) RmComment(ctx context.Context, userId, commentId int64) (e errno.ErrNo, err error) {
|
||
|
ctx, persist := dbtx.WithTXPersist(ctx)
|
||
|
defer func() {
|
||
|
persist(err)
|
||
|
}()
|
||
|
|
||
|
commentModel, err := s.commentRepository.LoadById(ctx, commentId)
|
||
|
if err != nil {
|
||
|
return misc.SystemErr, err
|
||
|
}
|
||
|
|
||
|
comment, err := comment.New(
|
||
|
comment.WithId(commentModel.Id),
|
||
|
comment.WithVideoId(commentModel.VideoId),
|
||
|
comment.WithUserId(commentModel.UserId),
|
||
|
comment.WithConversationId(commentModel.ConversationId),
|
||
|
comment.WithLastId(commentModel.LastId),
|
||
|
comment.WithToUserId(commentModel.ToUserId),
|
||
|
comment.WithContent(commentModel.Content),
|
||
|
comment.WithTimestamp(commentModel.Timestamp),
|
||
|
comment.WithStatus(commentModel.Status),
|
||
|
comment.WithCreatedAt(commentModel.CreatedAt),
|
||
|
comment.WithUpdatedAt(commentModel.UpdatedAt),
|
||
|
)
|
||
|
if err != nil {
|
||
|
return misc.SystemErr, err
|
||
|
}
|
||
|
|
||
|
_, err = comment.IsBelongUser(userId)
|
||
|
if err != nil {
|
||
|
return misc.SystemErr, err
|
||
|
}
|
||
|
|
||
|
comment.MarkAsDelete()
|
||
|
|
||
|
if err := s.commentRepository.Update(ctx, comment.ToModel()); err != nil {
|
||
|
return misc.SystemErr, err
|
||
|
}
|
||
|
|
||
|
if err := s.commentHBRepository.Save(ctx, comment.ToHBModel()); err != nil {
|
||
|
return misc.SystemErr, err
|
||
|
}
|
||
|
|
||
|
s.updateCacheComCount(comment.VideoId, false)
|
||
|
|
||
|
return misc.Success, nil
|
||
|
}
|