feat:添加热榜功能并添加了增加热度的方法。
This commit is contained in:
@@ -10,10 +10,11 @@ import (
|
||||
type CommentHandler struct {
|
||||
service *CommentService
|
||||
accountService *account.AccountService
|
||||
videoService *VideoService
|
||||
}
|
||||
|
||||
func NewCommentHandler(service *CommentService, accountService *account.AccountService) *CommentHandler {
|
||||
return &CommentHandler{service: service, accountService: accountService}
|
||||
func NewCommentHandler(service *CommentService, accountService *account.AccountService, videoService *VideoService) *CommentHandler {
|
||||
return &CommentHandler{service: service, accountService: accountService, videoService: videoService}
|
||||
}
|
||||
func (h *CommentHandler) PublishComment(c *gin.Context) {
|
||||
var req PublishCommentRequest
|
||||
@@ -49,6 +50,10 @@ 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"})
|
||||
}
|
||||
|
||||
@@ -71,6 +76,7 @@ func (h *CommentHandler) DeleteComment(c *gin.Context) {
|
||||
c.JSON(400, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, gin.H{"message": "comment deleted successfully"})
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,3 @@ type Like struct {
|
||||
type LikeRequest struct {
|
||||
VideoID uint `json:"video_id"`
|
||||
}
|
||||
|
||||
type LikeHandler struct {
|
||||
service *LikeService
|
||||
}
|
||||
|
||||
@@ -6,8 +6,13 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func NewLikeHandler(service *LikeService) *LikeHandler {
|
||||
return &LikeHandler{service: service}
|
||||
type LikeHandler struct {
|
||||
service *LikeService
|
||||
videoService *VideoService
|
||||
}
|
||||
|
||||
func NewLikeHandler(service *LikeService, videoService *VideoService) *LikeHandler {
|
||||
return &LikeHandler{service: service, videoService: videoService}
|
||||
}
|
||||
|
||||
func (lh *LikeHandler) Like(c *gin.Context) {
|
||||
@@ -35,6 +40,10 @@ func (lh *LikeHandler) Like(c *gin.Context) {
|
||||
c.JSON(500, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if err := lh.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": "like success"})
|
||||
}
|
||||
|
||||
@@ -63,6 +72,10 @@ func (lh *LikeHandler) Unlike(c *gin.Context) {
|
||||
c.JSON(500, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if err := lh.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": "unlike success"})
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ type Video struct {
|
||||
CoverURL string `gorm:"type:varchar(255);not null" json:"cover_url"`
|
||||
CreateTime time.Time `gorm:"autoCreateTime" json:"create_time"`
|
||||
LikesCount int64 `gorm:"column:likes_count;not null;default:0" json:"likes_count"`
|
||||
Popularity int64 `gorm:"column:popularity;not null;default:0" json:"popularity"`
|
||||
}
|
||||
|
||||
type PublishVideoRequest struct {
|
||||
|
||||
@@ -68,3 +68,12 @@ func (vr *VideoRepository) IsExist(ctx context.Context, id uint) (bool, error) {
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (vr *VideoRepository) UpdatePopularity(ctx context.Context, id uint, change int64) error {
|
||||
if err := vr.db.WithContext(ctx).Model(&Video{}).
|
||||
Where("id = ?", id).
|
||||
Update("popularity", gorm.Expr("popularity + ?", change)).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -166,3 +167,26 @@ func (vs *VideoService) UpdateLikesCount(ctx context.Context, id uint, likesCoun
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vs *VideoService) UpdatePopularity(ctx context.Context, id uint, change int64) error {
|
||||
if err := vs.repo.UpdatePopularity(ctx, id, change); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if vs.cache != nil {
|
||||
// 1) 详情缓存:直接失效(最简单靠谱)
|
||||
_ = vs.cache.Del(context.Background(), fmt.Sprintf("video:detail:id=%d", id))
|
||||
|
||||
// 2) 热榜:写到“时间窗ZSET”,不要用 detail key
|
||||
now := time.Now().UTC().Truncate(time.Minute)
|
||||
windowKey := "hot:video:1m:" + now.Format("200601021504")
|
||||
member := strconv.FormatUint(uint64(id), 10)
|
||||
|
||||
opCtx, cancel := context.WithTimeout(ctx, 50*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
_ = vs.cache.ZincrBy(opCtx, windowKey, member, float64(change))
|
||||
_ = vs.cache.Expire(opCtx, windowKey, 2*time.Hour)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user