package configser import ( "context" "sort" "sync" "videoweb/app/api/proto" "videoweb/pub/common/log" "videoweb/pub/models/actress" "videoweb/pub/models/contenttagmod" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo/options" ) type TopicCache struct { Lock sync.RWMutex // 读写锁 ActressWorks []proto.ActressInfoData ActressModelMaps map[int64]*actress.Actress AllTagMaps map[int64]proto.TagsInfoData VideoTagMaps map[int64]proto.TagsInfoData // 首页展示的标签,按当前类型绑定数量降序 HomeVideoTagList []proto.TagsInfoData HomePlayletTagList []proto.TagsInfoData } var TopicMgr TopicCache func StartTopicCache() { TopicMgr = TopicCache{} TopicMgr.Lock = sync.RWMutex{} TopicMgr.ActressWorks = make([]proto.ActressInfoData, 0) TopicMgr.ActressModelMaps = make(map[int64]*actress.Actress) TopicMgr.HomeVideoTagList = make([]proto.TagsInfoData, 0) TopicMgr.HomePlayletTagList = make([]proto.TagsInfoData, 0) TopicMgr.AllTagMaps = make(map[int64]proto.TagsInfoData) TopicMgr.VideoTagMaps = make(map[int64]proto.TagsInfoData) updateTagCache() updateCreateCache(context.Background()) updateCategoryCache() _, _ = skdCron.AddFunc("0 */5 * * * ?", func() { updateTagCache() updateCreateCache(context.Background()) updateCategoryCache() }) } func updateTagCache() { updateContentTagCache() } func updateCategoryCache() { updateActressCache() } func updateActressCache() { ctx := context.Background() filter := bson.M{actress.FN.Actress.Status: true} config := GetConfigInfo() otps := &options.FindOptions{} otps.SetSort(bson.D{ {Key: actress.FN.Actress.HotValue, Value: -1}, {Key: actress.FN.Actress.Id, Value: -1}, }) list, err := actress.FindManyActresss(ctx, filter, otps) if err != nil { log.Warn("updateActressCache", log.E(err)) return } tempWorks := make([]proto.ActressInfoData, len(list)) tempModel := make(map[int64]*actress.Actress) for i := 0; i < len(list); i++ { info := proto.ActressInfoToData(*list[i], config.ImgCdn) tempWorks[i] = info tempModel[info.Id] = list[i] } sort.SliceStable(tempWorks, func(i, j int) bool { if tempWorks[i].HotValue == tempWorks[j].HotValue { return tempWorks[i].Id > tempWorks[j].Id } return tempWorks[i].HotValue > tempWorks[j].HotValue }) TopicMgr.Lock.Lock() defer TopicMgr.Lock.Unlock() TopicMgr.ActressWorks = tempWorks TopicMgr.ActressModelMaps = tempModel } func GetActressInfo(actressId int64) *actress.Actress { TopicMgr.Lock.RLock() defer TopicMgr.Lock.RUnlock() v, ok := TopicMgr.ActressModelMaps[actressId] if !ok { return nil } return v } func updateContentTagCache() { ctx := context.Background() filter := bson.M{ contenttagmod.FN.ContentTag.Status: true, "$or": []bson.M{ {contenttagmod.FN.ContentTag.VideoCount: bson.M{"$gt": 0}}, {contenttagmod.FN.ContentTag.PlayletCount: bson.M{"$gt": 0}}, }, } list, err := contenttagmod.FindManyContentTag(ctx, filter, options.Find(). SetSort(bson.D{ {Key: contenttagmod.FN.ContentTag.Rank, Value: -1}, {Key: contenttagmod.FN.ContentTag.Id, Value: -1}, }). SetProjection(bson.M{ contenttagmod.FN.ContentTag.Id: 1, contenttagmod.FN.ContentTag.Name: 1, contenttagmod.FN.ContentTag.Slug: 1, contenttagmod.FN.ContentTag.Types: 1, contenttagmod.FN.ContentTag.Rank: 1, contenttagmod.FN.ContentTag.VideoCount: 1, contenttagmod.FN.ContentTag.PlayletCount: 1, "seoInfo": 1, })) if err != nil { log.Warn("updateContentTagCache", log.E(err)) return } allMaps := make(map[int64]proto.TagsInfoData, len(list)) videoMaps := make(map[int64]proto.TagsInfoData) videoHomeList := make([]proto.TagsInfoData, 0) playletHomeList := make([]proto.TagsInfoData, 0) for _, item := range list { if item == nil { continue } for _, tagType := range item.Types { info := contentTagInfoByType(item, tagType) allMaps[item.Id] = info switch tagType { case contenttagmod.ContentTagTypeVideo: videoMaps[item.Id] = info if info.Works > 0 { videoHomeList = append(videoHomeList, info) } case contenttagmod.ContentTagTypePlaylet: if info.Works > 0 { playletHomeList = append(playletHomeList, info) } } } } sortHomeContentTagList(videoHomeList) sortHomeContentTagList(playletHomeList) TopicMgr.Lock.Lock() defer TopicMgr.Lock.Unlock() TopicMgr.AllTagMaps = allMaps TopicMgr.VideoTagMaps = videoMaps TopicMgr.HomeVideoTagList = videoHomeList TopicMgr.HomePlayletTagList = playletHomeList } func contentTagInfoByType(item *contenttagmod.ContentTag, tagType contenttagmod.ContentTagType) proto.TagsInfoData { return proto.TagsInfoData{ Id: item.Id, Name: item.Name, Slug: item.Slug, SeoInfo: item.SeoInfo, Works: contentTagWorksByType(item, tagType), } } func contentTagWorksByType(item *contenttagmod.ContentTag, tagType contenttagmod.ContentTagType) int64 { switch tagType { case contenttagmod.ContentTagTypeVideo: return item.VideoCount case contenttagmod.ContentTagTypePlaylet: return item.PlayletCount default: return 0 } } func sortHomeContentTagList(list []proto.TagsInfoData) { sort.Slice(list, func(i, j int) bool { if list[i].Works == list[j].Works { return list[i].Id > list[j].Id } return list[i].Works > list[j].Works }) } func GetActressWorks() []proto.ActressInfoData { TopicMgr.Lock.RLock() defer TopicMgr.Lock.RUnlock() return TopicMgr.ActressWorks } func GetVideoTag(tagId int64) *proto.TagsInfoData { TopicMgr.Lock.RLock() defer TopicMgr.Lock.RUnlock() tag, ok := TopicMgr.VideoTagMaps[tagId] if !ok { return nil } return &tag } // VideoTagNamesAndSlugs 按视频标签ID顺序返回名称和slug func VideoTagNamesAndSlugs(tagIDs []int64) ([]string, []string) { names := make([]string, 0, len(tagIDs)) slugs := make([]string, 0, len(tagIDs)) TopicMgr.Lock.RLock() defer TopicMgr.Lock.RUnlock() for _, id := range tagIDs { if tag, ok := TopicMgr.VideoTagMaps[id]; ok { names = append(names, tag.Name) slugs = append(slugs, tag.Slug) } } return names, slugs } func GetHomeVideoTagList() []proto.TagsInfoData { TopicMgr.Lock.RLock() defer TopicMgr.Lock.RUnlock() return TopicMgr.HomeVideoTagList } func GetHomePlayletTagList() []proto.TagsInfoData { TopicMgr.Lock.RLock() defer TopicMgr.Lock.RUnlock() return TopicMgr.HomePlayletTagList }