feat: 评论相关rabbitMQ

This commit is contained in:
Leon
2025-12-30 01:25:54 +08:00
parent 475dfbe8da
commit 631cb2203f
4 changed files with 263 additions and 10 deletions

View File

@@ -10,11 +10,10 @@ import (
type CommentHandler struct {
service *CommentService
accountService *account.AccountService
videoService *VideoService
}
func NewCommentHandler(service *CommentService, accountService *account.AccountService, videoService *VideoService) *CommentHandler {
return &CommentHandler{service: service, accountService: accountService, videoService: videoService}
func NewCommentHandler(service *CommentService, accountService *account.AccountService) *CommentHandler {
return &CommentHandler{service: service, accountService: accountService}
}
func (h *CommentHandler) PublishComment(c *gin.Context) {
var req PublishCommentRequest
@@ -50,10 +49,6 @@ func (h *CommentHandler) PublishComment(c *gin.Context) {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if err := h.videoService.UpdatePopularity(c.Request.Context(), req.VideoID, 1); err != nil {
c.JSON(500, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"message": "comment published successfully"})
}

View File

@@ -3,18 +3,38 @@ package video
import (
"context"
"errors"
"feedsystem_video_go/internal/middleware/rabbitmq"
rediscache "feedsystem_video_go/internal/middleware/redis"
"strings"
"gorm.io/gorm"
)
type CommentService struct {
repo *CommentRepository
VideoRepository *VideoRepository
cache *rediscache.Client
commentMQ *rabbitmq.CommentMQ
popularityMQ *rabbitmq.PopularityMQ
}
func NewCommentService(repo *CommentRepository, videoRepo *VideoRepository) *CommentService {
return &CommentService{repo: repo, VideoRepository: videoRepo}
func NewCommentService(repo *CommentRepository, videoRepo *VideoRepository, cache *rediscache.Client, commentMQ *rabbitmq.CommentMQ, popularityMQ *rabbitmq.PopularityMQ) *CommentService {
return &CommentService{repo: repo, VideoRepository: videoRepo, cache: cache, commentMQ: commentMQ, popularityMQ: popularityMQ}
}
func (s *CommentService) Publish(ctx context.Context, comment *Comment) error {
if comment == nil {
return errors.New("comment is nil")
}
comment.Username = strings.TrimSpace(comment.Username)
comment.Content = strings.TrimSpace(comment.Content)
if comment.VideoID == 0 || comment.AuthorID == 0 {
return errors.New("video_id and author_id are required")
}
if comment.Content == "" {
return errors.New("content is required")
}
exists, err := s.VideoRepository.IsExist(ctx, comment.VideoID)
if err != nil {
return err
@@ -22,7 +42,47 @@ func (s *CommentService) Publish(ctx context.Context, comment *Comment) error {
if !exists {
return errors.New("video not found")
}
return s.repo.CreateComment(ctx, comment)
mysqlEnqueued := false
redisEnqueued := false
if s.commentMQ != nil {
if err := s.commentMQ.Publish(ctx, comment.Username, comment.VideoID, comment.AuthorID, comment.Content); err == nil {
mysqlEnqueued = true
}
}
if s.popularityMQ != nil {
if err := s.popularityMQ.Update(ctx, comment.VideoID, 1); err == nil {
redisEnqueued = true
}
}
if mysqlEnqueued && redisEnqueued {
return nil
}
// Fallback: direct MySQL write when comment MQ publish fails.
if !mysqlEnqueued {
if err := s.repo.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
if err := tx.Select("id").First(&Video{}, comment.VideoID).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("video not found")
}
return err
}
if err := tx.Create(comment).Error; err != nil {
return err
}
return tx.Model(&Video{}).Where("id = ?", comment.VideoID).
UpdateColumn("popularity", gorm.Expr("popularity + 1")).Error
}); err != nil {
return err
}
}
// Fallback: direct Redis update when popularity MQ publish fails.
if !redisEnqueued {
UpdatePopularityCache(ctx, s.cache, comment.VideoID, 1)
}
return nil
}
func (s *CommentService) Delete(ctx context.Context, commentID uint, accountID uint) error {
@@ -36,6 +96,11 @@ func (s *CommentService) Delete(ctx context.Context, commentID uint, accountID u
if comment.AuthorID != accountID {
return errors.New("permission denied")
}
if s.commentMQ != nil {
if err := s.commentMQ.Delete(ctx, commentID); err == nil {
return nil
}
}
return s.repo.DeleteComment(ctx, comment)
}