diff --git a/apollostruct/restricted_visitor.go b/apollostruct/restricted_visitor.go index 16585ff7..b0c57980 100644 --- a/apollostruct/restricted_visitor.go +++ b/apollostruct/restricted_visitor.go @@ -7,6 +7,6 @@ type RestrictedVisitorCfg struct { } type RestrictedVisitorMomentCfg struct { - RestrictedVisitorMids []int64 `json:"restricted_visitor_mids"` // 限制可见范围的访客mids - RestrictedVisitorVisibleMomentIds []int64 `json:"restricted_visitor_visible_moment_ids"` // 限制访客可见的动态ids + RestrictedVisitorMids []int64 `json:"restricted_visitor_mids"` // 限制可见范围的访客mids + RestrictedVisitorVisibleMids []int64 `json:"restricted_visitor_visible_mids"` // 限制访客可见的动态mids } diff --git a/app/mix/service/apiservice.go b/app/mix/service/apiservice.go index 6cb4cef4..4952e13e 100644 --- a/app/mix/service/apiservice.go +++ b/app/mix/service/apiservice.go @@ -1952,55 +1952,58 @@ func (s *Service) ApiGetMomentRecommList(ctx *gin.Context, req *momentproto.ApiR ec = errcode.ErrCodeMomentSrvOk - // 1.查找本时段有无新发动态 - ids, err := s.utilGetMomentRecentListIds(ctx, req.Mid, req.OpType, consts.MomentRecommThroughput) - if err != nil { - logger.Error("utilGetMomentRecentListIds fail, err: %v", err) - ec = errcode.ErrCodeMomentSrvFail - return - } - - // 2.删去已查询的新动态 - recommThroughput := int64(consts.MomentRecommThroughput - len(ids)) - - // 3.补齐后续动态 - if recommThroughput > 0 { - recommIds, err := s.utilGetMomentRecommListIds(ctx, req.Mid, req.OpType, recommThroughput) - if err != nil { - logger.Error("utilGetMomentRecommListIds fail, err: %v", err) - ec = errcode.ErrCodeMomentSrvFail - return - } - ids = append(ids, recommIds...) - } - - // 取apollo配置 + // 1.取apollo配置 cfg := &apollostruct.RestrictedVisitorMomentCfg{} - err = apollo.GetJson(consts.RestrictedVisitorMomentKey, &cfg, apollo.ApolloOpts().SetNamespace("application")) + err := apollo.GetJson(consts.RestrictedVisitorMomentKey, &cfg, apollo.ApolloOpts().SetNamespace("application")) if err != nil { logger.Error("Apollo read failed : %v", err) return nil, errcode.ErrCodeApolloReadFail } - // 查询是否限制访客 + // 2.查询是否限制访客 visitorMid := req.BaseRequest.Mid + isRestrictedMid := false for _, restricted_visitor_mid := range cfg.RestrictedVisitorMids { if restricted_visitor_mid == visitorMid { // 是限制访问的访客 - recommMap := make(map[int64]int64) - for _, momentId := range ids { - recommMap[momentId] = 1 - } - restrictedRecommList := make([]int64, 0) - for _, restrictedVisitorVisibleMomentId := range cfg.RestrictedVisitorVisibleMomentIds { - if recommMap[restrictedVisitorVisibleMomentId] == 1 { - restrictedRecommList = append(restrictedRecommList, restrictedVisitorVisibleMomentId) - } - } - ids = restrictedRecommList + isRestrictedMid = true break } } + // 3.根据是否限制,查出对应的id + ids := make([]int64, 0) + if isRestrictedMid { + recommIds, err := s.utilGetRestrictedMomentRecommListIds(ctx, req.Mid, req.OpType, consts.MomentRecommThroughput) + if err != nil { + logger.Error("utilGetRestrictedMomentRecommListIds fail, err: %v", err) + ec = errcode.ErrCodeMomentSrvFail + return + } + ids = append(ids, recommIds...) + } else { + // (1).查找本时段有无新发动态 + ids, err = s.utilGetMomentRecentListIds(ctx, req.Mid, req.OpType, consts.MomentRecommThroughput) + if err != nil { + logger.Error("utilGetMomentRecentListIds fail, err: %v", err) + ec = errcode.ErrCodeMomentSrvFail + return + } + + // (2).删去已查询的新动态 + recommThroughput := int64(consts.MomentRecommThroughput - len(ids)) + + // (3).补齐后续动态 + if recommThroughput > 0 { + recommIds, err := s.utilGetMomentRecommListIds(ctx, req.Mid, req.OpType, recommThroughput) + if err != nil { + logger.Error("utilGetMomentRecommListIds fail, err: %v", err) + ec = errcode.ErrCodeMomentSrvFail + return + } + ids = append(ids, recommIds...) + } + } + // 4.查询动态内容 recommMomentList, err = s.utilGetApiMomentVOListByIds(ctx, req.Mid, ids) if err != nil { diff --git a/app/mix/service/utilservice.go b/app/mix/service/utilservice.go index 0c458c1b..2f15ecac 100644 --- a/app/mix/service/utilservice.go +++ b/app/mix/service/utilservice.go @@ -1471,6 +1471,55 @@ func (s *Service) utilGetMomentRecommListIds(ctx *gin.Context, mid int64, opType return } +// 根据提供的用户mid和操作类型,从推荐列表中获取吞吐量大小的列表,并更新用户游标 +func (s *Service) utilGetRestrictedMomentRecommListIds(ctx *gin.Context, mid int64, opType int64, throughput int64) (ids []int64, err error) { + // 从redis中获取动态列表长度 + recommListLength, err := redis.GetRedisClient().LLen(consts.RedisMomentPrefix + "restricted_recomm_list") + if err != nil { + logger.Error("Redis read failed : %v", err) + return + } + if recommListLength == 0 { + return + } + + // 获取用户游标 + offset := int64(0) + + // 获取游标和是否已触底标志 + offset, bottomFlag, err := s.utilGetMomentRecommlistOffsetAndBottomeFlag(ctx, mid, opType, recommListLength, throughput) + if err != nil { + logger.Error("utilGetMomentRecommlistOffsetAndBottomeFlag fail, err: %v", err) + return + } + if bottomFlag == 1 { // 已触底 + return make([]int64, 0), nil + } + + // 向下操作,去尾 + upperBound := throughput + if opType == consts.Recomm_Down { + surplusVolume := recommListLength - offset + if surplusVolume < throughput { + upperBound = surplusVolume + } + } + + // 根据用户游标得到待查询ids + ids = make([]int64, 0) + for i := int64(0); i < upperBound; i++ { + index := (offset + i) % recommListLength + id, err := redis.GetRedisClient().LIndexInt64(consts.RedisMomentPrefix+"restricted_recomm_list", int(index)) + if err != nil { + logger.Error("Redis read failed : %v", err) + return make([]int64, 0), err + } + ids = append(ids, id) + } + + return +} + // 根据提供的ids,查询出动态,并填充主播、是否关注、是否点赞,并保证按照提供的顺序返回ApiMomentVO的list func (s *Service) utilGetApiMomentVOListByIds(ctx *gin.Context, visitorMid int64, ids []int64) (volist []*momentproto.ApiMomentVO, err error) { diff --git a/app/mix/service/xxljob_tasks.go b/app/mix/service/xxljob_tasks.go index f5d5c017..ab449296 100644 --- a/app/mix/service/xxljob_tasks.go +++ b/app/mix/service/xxljob_tasks.go @@ -13,8 +13,10 @@ import ( streamerproto "service/api/proto/streamer/proto" vasproto "service/api/proto/vas/proto" vericodeproto "service/api/proto/vericode/proto" + "service/apollostruct" "service/bizcommon/util" "service/dbstruct" + "service/library/apollo" "service/library/contentaudit/imageaudit" "service/library/contentaudit/textaudit" videomoderation "service/library/contentaudit/video_moderation" @@ -426,11 +428,33 @@ func (s *CronService) ReloadMomentRecommList(ctx context.Context, param *xxl.Run return fmt.Sprintf("OpGetMomentList fail, err: %v", err) } + // 取apollo配置 + cfg := &apollostruct.RestrictedVisitorMomentCfg{} + err = apollo.GetJson(consts.RestrictedVisitorMomentKey, &cfg, apollo.ApolloOpts().SetNamespace("application")) + if err != nil { + logger.Error("Apollo read failed : %v", err) + return "Apollo read failedl" + } + + // 查询限制访问动态 + restrictedlist, err := _DefaultMoment.OpListByMids(&gin.Context{}, &momentproto.OpListByMidsReq{ + Mids: cfg.RestrictedVisitorVisibleMids, + CtLowerBound: goproto.Int64(0), + }) + if err != nil { + logger.Error("OpGetMomentListByMids fail, err: %v", err) + return fmt.Sprintf("OpGetMomentListByMids fail, err: %v", err) + } + // 清缓存 if err := redis.GetRedisClient().Del(consts.RedisMomentPrefix + "recomm_list"); err != nil { logger.Error("Del redis cache fail, err: %v", err) return fmt.Sprintf("Del redis cache fail, err: %v", err) } + if err := redis.GetRedisClient().Del(consts.RedisMomentPrefix + "restricted_recomm_list"); err != nil { + logger.Error("Del redis cache fail, err: %v", err) + return fmt.Sprintf("Del redis cache fail, err: %v", err) + } if err := redis.GetRedisClient().Del(consts.RedisMomentPrefix + "recent_list_offset"); err != nil { logger.Error("Del redis cache fail, err: %v", err) return fmt.Sprintf("Del redis cache fail, err: %v", err) @@ -446,6 +470,15 @@ func (s *CronService) ReloadMomentRecommList(ctx context.Context, param *xxl.Run } } + for _, moment := range restrictedlist { + id := util.DerefInt64(moment.Id) + err := redis.GetRedisClient().RPush(consts.RedisMomentPrefix+"restricted_recomm_list", id) + if err != nil { + logger.Error("Redis cache fail, err: %v", err) + return fmt.Sprintf("Redis cache fail, err: %v", err) + } + } + logger.Info("Refresh moment recommendation list cached in redis accomplished...") return "Refresh moment recommendation list cached in redis accomplished" }