diff --git a/internal/video/like_handler.go b/internal/video/like_handler.go index 61cb8a5..7afaf37 100644 --- a/internal/video/like_handler.go +++ b/internal/video/like_handler.go @@ -89,21 +89,3 @@ func (lh *LikeHandler) IsLiked(c *gin.Context) { } c.JSON(200, gin.H{"is_liked": isLiked}) } - -func (lh *LikeHandler) GetLikesCount(c *gin.Context) { - var req LikeRequest - if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(400, gin.H{"error": err.Error()}) - return - } - if req.VideoID <= 0 { - c.JSON(400, gin.H{"error": "video_id is required"}) - return - } - likesCount, err := lh.service.GetLikesCount(c.Request.Context(), req.VideoID) - if err != nil { - c.JSON(500, gin.H{"error": err.Error()}) - return - } - c.JSON(200, gin.H{"likes_count": likesCount}) -} diff --git a/internal/video/like_repo.go b/internal/video/like_repo.go index cd690ac..51b2dfd 100644 --- a/internal/video/like_repo.go +++ b/internal/video/like_repo.go @@ -34,14 +34,3 @@ func (r *LikeRepository) IsLiked(ctx context.Context, videoID, accountID uint) ( } return count > 0, nil } - -func (r *LikeRepository) GetLikesCount(ctx context.Context, videoID uint) (int64, error) { - var count int64 - err := r.db.WithContext(ctx).Model(&Like{}). - Where("video_id = ?", videoID). - Count(&count).Error - if err != nil { - return 0, err - } - return count, nil -} diff --git a/internal/video/like_service.go b/internal/video/like_service.go index 7c911b8..f4fc242 100644 --- a/internal/video/like_service.go +++ b/internal/video/like_service.go @@ -4,6 +4,9 @@ import ( "context" "errors" "time" + + "github.com/go-sql-driver/mysql" + "gorm.io/gorm" ) type LikeService struct { @@ -15,69 +18,49 @@ func NewLikeService(repo *LikeRepository, videoRepo *VideoRepository) *LikeServi return &LikeService{repo: repo, VideoRepo: videoRepo} } -func (s *LikeService) Like(ctx context.Context, like *Like) error { - exists, err := s.VideoRepo.IsExist(ctx, like.VideoID) - if err != nil { - return err - } - if !exists { - return errors.New("video not found") - } +func isDupKey(err error) bool { + var me *mysql.MySQLError + return errors.As(err, &me) && me.Number == 1062 +} - isLiked, err := s.IsLiked(ctx, like.VideoID, like.AccountID) - if err != nil { - return err - } - if isLiked { - return errors.New("user has liked this video") - } +func (s *LikeService) Like(ctx context.Context, like *Like) error { like.CreatedAt = time.Now() - if err := s.repo.Like(ctx, like); err != nil { - return err - } - likesCount, err := s.GetLikesCount(ctx, like.VideoID) - if err != nil { - return err - } - if err := s.VideoRepo.UpdateLikesCount(ctx, like.VideoID, likesCount); err != nil { - return err - } - return nil + return s.repo.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + if err := tx.Select("id").First(&Video{}, like.VideoID).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return errors.New("video not found") + } + return err + } + if err := tx.Create(like).Error; err != nil { + if isDupKey(err) { + return errors.New("user has liked this video") + } + return err + } + if err := tx.Model(&Video{}).Where("id = ?", like.VideoID). + UpdateColumn("likes_count", gorm.Expr("likes_count + 1")).Error; err != nil { + return err + } + return nil + }) } func (s *LikeService) Unlike(ctx context.Context, like *Like) error { - exists, err := s.VideoRepo.IsExist(ctx, like.VideoID) - if err != nil { - return err - } - if !exists { - return errors.New("video not found") - } + return s.repo.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + del := tx.Where("video_id = ? AND account_id = ?", like.VideoID, like.AccountID).Delete(&Like{}) + if del.Error != nil { + return del.Error + } + if del.RowsAffected == 0 { + return errors.New("user has not liked this video") + } - isLiked, err := s.IsLiked(ctx, like.VideoID, like.AccountID) - if err != nil { - return err - } - if !isLiked { - return errors.New("user has not liked this video") - } - if err := s.repo.Unlike(ctx, like); err != nil { - return err - } - likesCount, err := s.GetLikesCount(ctx, like.VideoID) - if err != nil { - return err - } - if err := s.VideoRepo.UpdateLikesCount(ctx, like.VideoID, likesCount); err != nil { - return err - } - return nil + return tx.Model(&Video{}).Where("id = ?", like.VideoID). + UpdateColumn("likes_count", gorm.Expr("GREATEST(likes_count - 1, 0)")).Error + }) } func (s *LikeService) IsLiked(ctx context.Context, videoID, accountID uint) (bool, error) { return s.repo.IsLiked(ctx, videoID, accountID) } - -func (s *LikeService) GetLikesCount(ctx context.Context, videoID uint) (int64, error) { - return s.repo.GetLikesCount(ctx, videoID) -}