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 }