129 lines
4.2 KiB
Go
129 lines
4.2 KiB
Go
package configser
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"videoweb/app/api/proto"
|
|
"videoweb/pub/common/log"
|
|
"videoweb/pub/common/netutil"
|
|
"videoweb/pub/models/videoinformationmod"
|
|
"videoweb/pub/pubdef"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
)
|
|
|
|
var (
|
|
VideoRankMgr periodRankCache[proto.ContentData]
|
|
videoRankRefreshLock sync.Mutex
|
|
)
|
|
|
|
func UpdateVideoRankCache() {
|
|
ctx := context.Background()
|
|
imgCdn := GetConfigInfo().ImgCdn
|
|
VideoRankMgr.replace(
|
|
buildVideoRankList(ctx, imgCdn, RankPeriodTotal),
|
|
buildVideoRankList(ctx, imgCdn, RankPeriodWeek),
|
|
buildVideoRankList(ctx, imgCdn, RankPeriodMonth),
|
|
buildVideoRankList(ctx, imgCdn, RankPeriodYear),
|
|
)
|
|
}
|
|
|
|
func refreshVideoRankCacheIfEmpty() {
|
|
if VideoRankMgr.hasAny() {
|
|
return
|
|
}
|
|
videoRankRefreshLock.Lock()
|
|
defer videoRankRefreshLock.Unlock()
|
|
if VideoRankMgr.hasAny() {
|
|
return
|
|
}
|
|
UpdateVideoRankCache()
|
|
}
|
|
|
|
func GetVideoRankList(p RankPeriod, limit int) []proto.ContentData {
|
|
return VideoRankMgr.get(p, limit, refreshVideoRankCacheIfEmpty)
|
|
}
|
|
|
|
func videoPeriodWatchField(p RankPeriod) string {
|
|
switch p {
|
|
case RankPeriodWeek:
|
|
return videoinformationmod.FN.VideoInformation.Real.WeekWatchs
|
|
case RankPeriodMonth:
|
|
return videoinformationmod.FN.VideoInformation.Real.MonthWatchs
|
|
case RankPeriodYear:
|
|
return videoinformationmod.FN.VideoInformation.Real.YearWatchs
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func videoToContentData(item *videoinformationmod.VideoInformation, imgCdn string) proto.ContentData {
|
|
tagNames, tagSlugs := VideoTagNamesAndSlugs(item.Tags)
|
|
return proto.ContentData{
|
|
Id: item.Id,
|
|
Title: item.Title,
|
|
Slug: item.Slug,
|
|
AddedTime: item.AddedTime,
|
|
CoverImg: netutil.MergeURL(imgCdn, item.CoverImg),
|
|
Tags: item.Tags,
|
|
TagsName: tagNames,
|
|
TagSlugs: tagSlugs,
|
|
WatchNum: item.Real.WatchTimes + item.Fake.WatchTimes,
|
|
LikeNum: item.Real.Likes + item.Fake.Likes,
|
|
}
|
|
}
|
|
|
|
func videoToRankContentData(item *videoinformationmod.VideoInformation, imgCdn string, p RankPeriod) proto.ContentData {
|
|
data := videoToContentData(item, imgCdn)
|
|
data.WatchNum = periodWatchNum(p, item.Real.WeekWatchs, item.Real.MonthWatchs, item.Real.YearWatchs, data.WatchNum)
|
|
return data
|
|
}
|
|
|
|
func buildVideoRankList(ctx context.Context, imgCdn string, p RankPeriod) []proto.ContentData {
|
|
var ranked videoinformationmod.VideoInformationList
|
|
if p == RankPeriodTotal {
|
|
if err := videoinformationmod.AggregateVideoInformations(ctx, &ranked, contentLikeRankPipeline(
|
|
videoinformationmod.FN.VideoInformation.Status, pubdef.InformationStatusVerifyOK,
|
|
videoinformationmod.FN.VideoInformation.Real.Likes, videoinformationmod.FN.VideoInformation.Fake.Likes,
|
|
videoinformationmod.FN.VideoInformation.UpdatedAt, videoinformationmod.FN.VideoInformation.Id,
|
|
rankLimit,
|
|
)); err != nil {
|
|
log.Warn("buildVideoRankList like rank query failed", log.E(err))
|
|
ranked = videoinformationmod.VideoInformationList{}
|
|
}
|
|
} else {
|
|
watchField := videoPeriodWatchField(p)
|
|
list, err := videoinformationmod.FindManyVideoInformations(ctx, bson.M{
|
|
videoinformationmod.FN.VideoInformation.Status: pubdef.InformationStatusVerifyOK,
|
|
watchField: bson.M{"$gt": 0},
|
|
}, contentWatchRankOpts(watchField, videoinformationmod.FN.VideoInformation.UpdatedAt, videoinformationmod.FN.VideoInformation.Id, rankLimit))
|
|
if err != nil {
|
|
log.Warn("buildVideoRankList watch rank query failed", log.Any("period", p), log.E(err))
|
|
ranked = videoinformationmod.VideoInformationList{}
|
|
} else {
|
|
ranked = list
|
|
}
|
|
}
|
|
if int64(len(ranked)) < rankLimit {
|
|
needFill := rankLimit - int64(len(ranked))
|
|
excludeIds := make([]int64, 0, len(ranked))
|
|
for _, v := range ranked {
|
|
excludeIds = append(excludeIds, v.Id)
|
|
}
|
|
var filled videoinformationmod.VideoInformationList
|
|
if err := videoinformationmod.AggregateVideoInformations(ctx, &filled, contentRankFillPipeline(
|
|
videoinformationmod.FN.VideoInformation.Id, videoinformationmod.FN.VideoInformation.Status,
|
|
pubdef.InformationStatusVerifyOK, excludeIds, needFill,
|
|
)); err != nil {
|
|
log.Warn("buildVideoRankList fill sample failed", log.Any("period", p), log.E(err))
|
|
} else {
|
|
ranked = append(ranked, filled...)
|
|
}
|
|
}
|
|
result := make([]proto.ContentData, 0, len(ranked))
|
|
for _, item := range ranked {
|
|
result = append(result, videoToRankContentData(item, imgCdn, p))
|
|
}
|
|
return result
|
|
}
|