You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1279 lines
45 KiB

package v1
import (
"context"
"encoding/json"
"fmt"
"net/url"
"reflect"
"strconv"
"sync/atomic"
"time"
v1indexpb "go-common/app/interface/live/app-interface/api/http/v1"
"go-common/app/interface/live/app-interface/conf"
"go-common/app/interface/live/app-interface/dao"
liveuserV1 "go-common/app/service/live/live_user/api/liverpc/v1"
relationV2 "go-common/app/service/live/relation/api/liverpc/v2"
roomV1 "go-common/app/service/live/room/api/liverpc/v1"
roomV2 "go-common/app/service/live/room/api/liverpc/v2"
bannerV1 "go-common/app/service/live/room_ex/api/liverpc/v1"
"go-common/app/service/live/third_api/bvc"
userextV1 "go-common/app/service/live/userext/api/liverpc/v1"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/net/rpc/liverpc"
rpcCtx "go-common/library/net/rpc/liverpc/context"
"go-common/library/sync/errgroup"
"go-common/library/xstr"
"math/rand"
"github.com/bitly/go-simplejson"
"github.com/pkg/errors"
"go-common/library/net/http/blademaster"
)
const (
_bannerType = 1
_navigatorType = 2
_yunyingRecFormType = 3
_yunyingRecSquareType = 4
_recFormType = 6
_recSquareType = 7
_feedType = 8
_parentAreaFormType = 9
_parentAreaSquareType = 10
_myAreaTagType = 12
_seaPatrolType = 14
_myAreaTagListType = 13
_activityType = 11
// _recTypeOnline = 1
// _recTypeIncome = 2
_recTypeForce = 3
_recTypeSkyHorse = 4
_defaultRecNum = 24
_skyHorseRecTimeOut = 100
_areaModuleLink = "https://live.bilibili.com/app/area?parent_area_id=%d&parent_area_name=%s&area_id=%d&area_name=%s"
_activityGo = 0
_activityBook = 1
_activityUnbook = 2
_mobileIndexBadgeColorDefault = "#FB9E60"
)
// Service struct
type Service struct {
conf *conf.Config
// optionally add other properties here, such as dao
dao *dao.Dao
allListInfo atomic.Value
}
type roomItem struct {
RoomId int64 `json:"roomid"`
Title string `json:"title"`
Uname string `json:"uname"`
Online int64 `json:"online"`
Cover string `json:"cover"`
Link string `json:"link"`
Face string `json:"face"`
AreaV2ParentId int64 `json:"area_v2_parent_id"`
AreaV2ParentName string `json:"area_v2_parent_name"`
AreaV2Id int64 `json:"area_v2_id"`
AreaV2Name string `json:"area_v2_name"`
PlayUrl string `json:"play_url"`
PlayUrlH265 string `json:"play_url_h265"`
CurrentQuality int64 `json:"current_quality"`
BroadcastType int64 `json:"broadcast_type"`
PendentRu string `json:"pendent_ru"`
PendentRuPic string `json:"pendent_ru_pic"`
PendentRuColor string `json:"pendent_ru_color"`
RecType int64 `json:"rec_type"`
PkId int64 `json:"pk_id"`
AcceptQuality []int64 `json:"accept_quality"`
}
type offlineItem struct {
Id int `json:"id"`
Name string `json:"name"`
}
type userTagItem struct {
AreaV2Id int `json:"area_v2_id"`
AreaV2Name string `json:"area_v2_name"`
AreaV2ParentId int `json:"area_v2_parent_id"`
AreaV2ParentName string `json:"area_v2_parent_name"`
Pic string `json:"pic"`
Link string `json:"link"`
IsAdvice int `json:"is_advice"`
}
type commonResp struct {
ModuleInfo map[string]interface{}
ExtraInfo map[string]interface{}
List interface{}
}
type ModuleResp struct {
Interval int `json:"interval"`
ModuleList []map[string]interface{} `json:"module_list"`
}
// New init
func New(c *conf.Config) (s *Service) {
s = &Service{
conf: c,
dao: dao.New(c),
}
go s.tickCacheAllList(context.TODO())
return s
}
// GetAllList implementation
// 首页大接口
func (s *Service) GetAllList(ctx context.Context, req *v1indexpb.GetAllListReq) (ret interface{}, err error) {
resp := &ModuleResp{
Interval: 10,
}
build := req.Build
relationTimeout := conf.GetTimeout("relation", 200)
// dao.LiveUserApi.V1UserSetting.GetTag(ctx, &liveuserV1.UserSettingGetTagReq{})
midInterface, isUIDSet := metadata.Value(ctx, metadata.Mid).(int64) // 大多使用header里的mid解析, 框架已封装请求的header
isSkyHorseGray := false
mid := int64(0)
if isUIDSet {
mid = midInterface
// 天马灰度
isSkyHorseGray = s.isSkyHorseRec(mid)
}
buvid := ""
// 主站封好的,可从device里获取到sid、buvid、buvid3、build、channel、device、mobi_app、platform
device, ok := metadata.Value(ctx, metadata.Device).(*blademaster.Device)
if ok {
buvid = device.Buvid
}
// deviceInterface := req.Device
// device := deviceInterface.(*bm.Device)
if req.Platform == "" || req.Device == "" || req.Scale == "" || req.RelationPage == 0 {
err = errors.WithMessage(ecode.InvalidParam, "INVALID PARAM")
return
}
allListTimeout := time.Duration(conf.GetTimeout("allList", 50)) * time.Millisecond
rawModuleList := s.getAllListFromCache(rpcCtx.WithTimeout(ctx, allListTimeout))
if rawModuleList == nil {
err = errors.WithMessage(ecode.GetAllListReturnError, "")
return
}
// 大分区常量定义
parentName := map[int64]string{
1: "娱乐",
2: "游戏",
3: "手游",
4: "绘画",
5: "电台",
}
// 天马灰度/保底
defaultRecSlice := make([]map[string]interface{}, 0)
loginRecRoomIDSlice := make([]int64, 0)
// [{module_info:{},list:{}}...]
resp.ModuleList = make([]map[string]interface{}, len(rawModuleList))
for _, m := range rawModuleList {
module := m.(map[string]interface{})
if module["module_info"] == nil {
log.Error("empty_module_info:%+v \n", m)
fmt.Printf("empty_module_info:raw_all:%+v \n", rawModuleList)
}
moduleInfo := module["module_info"].(map[string]interface{})
moduleType := jsonMustInt(moduleInfo["type"], 0)
if moduleType == 0 {
continue
}
list := module["list"].([]interface{})
if moduleType == _recFormType || moduleType == _recSquareType {
for _, r := range list {
recItem := r.(map[string]interface{})
defaultRecSlice = append(defaultRecSlice, recItem)
roomID := jsonMustInt(recItem["roomid"], 0)
if roomID == 0 {
continue
}
// 登录了也有可能请求不到数据,登录的保底用
loginRecRoomIDSlice = append(loginRecRoomIDSlice, roomID)
}
}
}
// 常用标签 roomListMap
myTagRoomListMap := make(map[int64][]*roomV2.AppIndexGetMultiRoomListResp_RoomList)
myTagAreaIds := make([]int64, 0, 4)
myTagAreaInfoMap := make(map[int64]*liveuserV1.UserSettingGetTagResp_Tags)
myTagResp := commonResp{
List: make([]interface{}, 0),
}
attentionResp := commonResp{
List: make([]interface{}, 0),
}
loginRecResp := commonResp{}
seaResp := commonResp{}
bannerResp := commonResp{
List: make([]interface{}, 0),
}
// playurl定义
attentionRoomListPlayURLMap := make(map[int64]*bvc.PlayUrlItem)
loginRecRoomListPlayURLMap := make(map[int64]*bvc.PlayUrlItem)
myTagRoomListPlayURLMap := make(map[int64]*bvc.PlayUrlItem)
otherRoomListPlayURLMap := make(map[int64]*bvc.PlayUrlItem)
otherRoomIDSlice := make([]int64, 0)
isSkyHorseGrayOk := 0
// 此group包含首页的一些任务
// 但是任务之间不能同时cancel
// 不然一个接口出错所有任务都cancel首页就空了
// 所以return固定为nil(一个wg的任务使用的是从bm context继承来的ctx,cancel后一起推出)
// 只有上层ctx(http的ctx)出问题(超时等)才会退出后续任务1
wg, _ := errgroup.WithContext(ctx)
for _, m := range rawModuleList {
// {module_info:xx}
module := m.(map[string]interface{})
// {id:xx,type:xx,pic:xx,title:xx,link:xx,...}
moduleInfo := module["module_info"].(map[string]interface{})
moduleList := module["list"].([]interface{})
moduleType := jsonMustInt(moduleInfo["type"], 0)
if moduleType == 0 {
continue
}
// banner分支 分端分版本
if moduleType == _bannerType {
bannerTimeout := time.Duration(conf.GetTimeout("banner", 100)) * time.Millisecond
wg.Go(func() error {
bannerList, bannerErr := dao.RoomExtApi.V1Banner.GetNewBanner(rpcCtx.WithTimeout(ctx, time.Duration(bannerTimeout)*time.Millisecond), &bannerV1.BannerGetNewBannerReq{UserPlatform: req.Platform, Build: build, UserDevice: req.Device})
if bannerErr != nil {
log.Error("[GetAllList]get banner rpc error, roomex.v1.Banner.GetNewBanner, error:%+v,rpctimeout:%d", bannerErr, bannerTimeout)
return nil
}
if bannerList.Code != 0 || bannerList.Data == nil {
log.Error("[GetAllList]get banner response error, code, %d, msg: %s, error:%+v", bannerList.Code, bannerList.Msg, bannerErr)
return nil
}
if len(bannerList.Data) > 0 {
for _, bannerInfo := range bannerList.Data {
bannerResp.List = append(bannerResp.List.([]interface{}), map[string]interface{}{
"id": bannerInfo.Id,
"pic": bannerInfo.Pic,
"link": bannerInfo.Link,
"title": bannerInfo.Title,
})
}
}
return nil
})
}
// 关注分支
if moduleType == _feedType {
if !isUIDSet {
continue
}
wg.Go(func() error {
currentAttentionRoomMap := make(map[int64]bool)
currentAttentionRoomSlice := make([]int64, 0)
attentionResp.ModuleInfo = moduleInfo
currentAttention, attentionErr := dao.RelationApi.V2App.LiveHomePage(rpcCtx.WithTimeout(ctx, time.Duration(relationTimeout)*time.Millisecond), &relationV2.AppLiveHomePageReq{RelationPage: req.RelationPage})
if attentionErr != nil {
log.Error("[GetAllList]get user attention rpc error, relation.v2.App.liveHomePage, error:%+v,rpctimeout:%d", attentionErr, relationTimeout)
} else if currentAttention.Code != 0 || currentAttention.Data == nil {
log.Error("[GetAllList]get user attention response error, code, %d, msg: %s, error:%+v", currentAttention.Code, currentAttention.Msg, attentionErr)
} else {
attentionResp.ExtraInfo = map[string]interface{}{
"total_count": currentAttention.Data.TotalCount,
"time_desc": currentAttention.Data.TimeDesc,
"uname_desc": currentAttention.Data.UnameDesc,
"tags_desc": currentAttention.Data.TagsDesc,
"relation_page": currentAttention.Data.RelationPage,
}
// 存关注map
for _, attentionCard := range currentAttention.Data.Rooms {
currentAttentionRoomMap[attentionCard.Roomid] = true
currentAttentionRoomSlice = append(currentAttentionRoomSlice, attentionCard.Roomid)
attentionResp.List = append(attentionResp.List.([]interface{}), attentionCard)
}
// playurl
attentionRoomListPlayURLMap = dao.BvcApi.GetPlayUrlMulti(ctx, currentAttentionRoomSlice, 0, 4, build, req.Platform)
}
useDefaultRec := false
isOpen := conf.Conf.SkyHorseStatus
if isOpen && isSkyHorseGray {
// 取天马数据,传入关注当前刷列表roomid+强推,天马会对传入的roomid去重
// duplicates := append(currentAttentionRoomSlice, forceRecSlice...)
// getSkyHorseRoomList已经对强推去重
duplicates := currentAttentionRoomSlice
skyRecResult, skyHorseErr := getSkyHorseRoomList(ctx, mid, buvid, req.Build, req.Platform, duplicates, 1)
if skyHorseErr != nil {
log.Warn("[GetAllList]get data from skyHorse err: %v", skyHorseErr)
useDefaultRec = true
}
if skyRecResult == nil {
log.Warn("[GetAllList]get data from skyHorse empty: %v", skyHorseErr)
useDefaultRec = true
}
if len(skyRecResult) < 6 {
log.Warn("[GetAllList]get data from skyHorse not enough: %v", skyRecResult)
useDefaultRec = true
}
skyRecResultInterface := make([]map[string]interface{}, 0)
for _, item := range skyRecResult {
loginRecRoomIDSlice = append(loginRecRoomIDSlice, item.RoomId)
skyRecResultInterface = append(skyRecResultInterface, map[string]interface{}{
"roomid": item.RoomId,
"title": item.Title,
"uname": item.Uname,
"online": item.Online,
"cover": item.Cover,
"link": item.Link,
"face": item.Face,
"area_v2_parent_id": item.AreaV2ParentId,
"area_v2_parent_name": item.AreaV2ParentName,
"area_v2_id": item.AreaV2Id,
"area_v2_name": item.AreaV2Name,
"play_url": item.PlayUrl,
"current_quality": item.CurrentQuality,
"broadcast_type": item.BroadcastType,
"pendent_ru": item.PendentRu,
"pendent_ru_pic": item.PendentRuPic,
"pendent_ru_color": item.PendentRuColor,
"rec_type": item.RecType,
"pk_id": item.PkId,
"accept_quality": item.AcceptQuality,
})
}
loginRecResp.List = skyRecResultInterface
isSkyHorseGrayOk = 1
}
// 保底逻辑
if !isOpen || !isSkyHorseGray || useDefaultRec {
newDefaultRecSlice := make([]map[string]interface{}, 0)
for _, defaultRecRoom := range defaultRecSlice {
roomID := jsonMustInt(defaultRecRoom["roomid"], 0)
if roomID == 0 {
continue
}
if _, exist := currentAttentionRoomMap[roomID]; !exist {
// 天马没取到保底:默认推荐要对关注当前刷去重
newDefaultRecSlice = append(newDefaultRecSlice, defaultRecRoom)
}
}
// 只返24个
if len(newDefaultRecSlice) > _defaultRecNum {
loginRecResp.List = newDefaultRecSlice[:_defaultRecNum]
} else {
loginRecResp.List = newDefaultRecSlice
}
isSkyHorseGrayOk = 0
}
loginRecRoomListPlayURLMap = dao.BvcApi.GetPlayUrlMulti(ctx, loginRecRoomIDSlice, 0, 4, build, req.Platform)
return nil
})
}
// 常用标签分支
if moduleType == _myAreaTagType {
wg.Go(func() error {
myTagResp.ModuleInfo = moduleInfo
getMyTagTimeout := time.Duration(conf.GetTimeout("getMyTag", 100)) * time.Millisecond
myTagListResp, userTagError := dao.LiveUserApi.V1UserSetting.GetTag(rpcCtx.WithTimeout(ctx, getMyTagTimeout), &liveuserV1.UserSettingGetTagReq{})
if userTagError != nil {
log.Error("[GetAllList]get user tag rpc error, live_user.v1.usersetting.get_tag, error:%+v", userTagError)
return nil // 如果return err 则所有当前group的任务都会cancel
}
if myTagListResp.Code != 0 || myTagListResp.Data == nil {
log.Error("[GetAllList]get user tag return error, code, %d, msg: %s, error:%+v", myTagListResp.Code, myTagListResp.Msg, userTagError)
return nil
}
if myTagListResp.Data != nil {
myTagResp.ExtraInfo = make(map[string]interface{})
myTagResp.ExtraInfo["is_gray"] = myTagListResp.Data.IsGray
myTagResp.ExtraInfo["offline"] = make([]interface{}, 0)
for _, offlineInfo := range myTagListResp.Data.Offline {
myTagResp.ExtraInfo["offline"] = append(myTagResp.ExtraInfo["offline"].([]interface{}), &offlineItem{Id: int(offlineInfo.Id), Name: offlineInfo.Name})
}
}
for _, tagInfo := range myTagListResp.Data.Tags {
myTagAreaIds = append(myTagAreaIds, tagInfo.Id)
myTagAreaInfoMap[tagInfo.Id] = tagInfo
link := fmt.Sprintf("http://live.bilibili.com/app/area?parent_area_id=%d&parent_area_name=%s&area_id=%d&area_name=%s", tagInfo.ParentId, parentName[tagInfo.ParentId], tagInfo.Id, tagInfo.Name)
myTagResp.List = append(myTagResp.List.([]interface{}), &userTagItem{AreaV2Id: int(tagInfo.Id), AreaV2Name: tagInfo.Name, AreaV2ParentId: int(tagInfo.ParentId), AreaV2ParentName: parentName[tagInfo.ParentId], Link: link, Pic: tagInfo.Pic, IsAdvice: int(tagInfo.IsAdvice)})
}
if (req.Platform == "ios" && build > 8220) || (req.Platform == "android" && build > 5333002) {
myTagResp.List = append(myTagResp.List.([]interface{}), &userTagItem{AreaV2Id: int(0), AreaV2Name: "全部标签", AreaV2ParentId: int(0), AreaV2ParentName: "", Pic: "http://i0.hdslb.com/bfs/vc/ff03528785fc8c91491d79e440398484811d6d87.png", Link: "http://live.bilibili.com/app/mytag/", IsAdvice: 1})
}
if len(myTagAreaIds) <= 0 {
log.Error("[GetAllList]get user tag return empty!uid:%d", mid)
return nil
}
// 常用标签房间列表 先生成最后wait替换就好了
getMultiRoomListTimeout := time.Duration(conf.GetTimeout("getMultiRoomList", 100)) * time.Millisecond
myTagRoomListResp, multiRoomListErr := dao.RoomApi.V2AppIndex.GetMultiRoomList(rpcCtx.WithTimeout(ctx, getMultiRoomListTimeout), &roomV2.AppIndexGetMultiRoomListReq{AreaIds: xstr.JoinInts(myTagAreaIds), Platform: req.Platform})
if multiRoomListErr != nil {
log.Error("[GetAllList]get multi list rpc error, room.v2.AppIndex.GetMultiRoomList, error:%+v", multiRoomListErr)
return nil
}
if myTagRoomListResp.Code != 0 || myTagRoomListResp.Data == nil {
log.Error("[GetAllList]get multi list response error, code, %d, msg: %s, error:%+v", myTagRoomListResp.Code, myTagRoomListResp.Msg, multiRoomListErr)
return nil
}
// 保存roomListMap,wait 聚合数据
myTagRoomIDSlice := make([]int64, 0)
for _, myTagRoomItem := range myTagRoomListResp.Data {
myTagRoomListMap[myTagRoomItem.Id] = myTagRoomItem.List
for _, item := range myTagRoomItem.List {
myTagRoomIDSlice = append(myTagRoomIDSlice, item.Roomid)
}
}
myTagRoomListPlayURLMap = dao.BvcApi.GetPlayUrlMulti(ctx, myTagRoomIDSlice, 0, 4, build, req.Platform)
return nil
})
}
if moduleType == _seaPatrolType {
seaPatrolList := make([]interface{}, 0)
if !isUIDSet {
continue
}
// 大航海分支
wg.Go(func() error {
seaPatrolTimeout := time.Duration(conf.GetTimeout("seaPatrol", 100)) * time.Millisecond
seaPatrol, seaPatrolError := dao.LiveUserApi.V1Note.Get(rpcCtx.WithTimeout(ctx, seaPatrolTimeout), &liveuserV1.NoteGetReq{})
if seaPatrolError != nil {
log.Error("[GetAllList]get sea patrol rpc error, liveuser.v1.Note.Get, error:%+v", seaPatrolError)
return nil
}
if seaPatrol.Code != 0 || seaPatrol.Data == nil {
log.Error("[GetAllList]get sea patrol note from liveuser response error, code, %d, msg: %s, error:%+v", seaPatrol.Code, seaPatrol.Msg, seaPatrolError)
return nil
}
if seaPatrol.Data.Title != "" {
seaPatrolList = append(seaPatrolList, map[string]interface{}{
"pic": seaPatrol.Data.Logo,
"title": seaPatrol.Data.Title,
"link": seaPatrol.Data.Link,
"content": seaPatrol.Data.Content,
})
}
seaResp.List = seaPatrolList
seaResp.ModuleInfo = moduleInfo
seaResp.ExtraInfo = make(map[string]interface{})
return nil
})
}
if moduleType == _activityType {
cardList := module["list"].([]interface{})
actyInfo := cardList[0].(map[string]interface{})
bookStatus := jsonMustInt(actyInfo["status"], 0)
// status=0(非预约类型的活动)
if bookStatus == _activityGo {
actyInfo["button_text"] = "去围观"
actyInfo["status"] = _activityGo
continue
}
// 未登入 显示预约
if !isUIDSet {
actyInfo["button_text"] = "预约"
actyInfo["status"] = _activityBook
continue
}
// 登入状态 设置保底数据
actyInfo["button_text"] = "去围观"
actyInfo["status"] = _activityGo
// 获取活动id
materialID := jsonMustInt(moduleInfo["material_id"], 0)
if materialID == 0 {
continue
}
log.Info("[GetAllList]materialID is %v", materialID)
wg.Go(func() error {
activityQueryTimeout := time.Duration(conf.GetTimeout("activityQuery", 100)) * time.Millisecond
bookInfo, userExtError := dao.UserExtApi.V1Remind.Query(rpcCtx.WithTimeout(ctx, activityQueryTimeout), &userextV1.RemindQueryReq{Aid: materialID})
if userExtError != nil {
log.Error("[GetAllList]get activity book info rpc error, userext.v1.Remind.Query, error:%+v", userExtError)
return nil
}
if bookInfo.Code != 0 {
log.Error("[GetAllList]get activity book info response error, code, %d, msg: %s, error:%+v", bookInfo.Code, bookInfo.Msg, userExtError)
return nil
}
log.Info("[GetAllList]materialID is %v and bookInfo.Data.Status is %v", materialID, bookInfo.Data.Status)
switch bookInfo.Data.Status {
case _activityBook:
actyInfo["button_text"] = "已预约"
actyInfo["status"] = _activityUnbook
case _activityUnbook:
actyInfo["button_text"] = "预约"
actyInfo["status"] = _activityBook
default:
actyInfo["button_text"] = "去围观"
actyInfo["status"] = _activityGo
}
return nil
})
}
// 其他playurl,注意这里取的推荐是未登录下的推荐play_url
if moduleType == _yunyingRecFormType || moduleType == _yunyingRecSquareType ||
moduleType == _parentAreaFormType || moduleType == _parentAreaSquareType ||
moduleType == _recFormType || moduleType == _recSquareType {
// append Roomid
for _, item := range moduleList {
itemV := item.(map[string]interface{})
roomID := jsonMustInt(itemV["roomid"], 0)
if roomID == 0 {
continue
}
otherRoomIDSlice = append(otherRoomIDSlice, roomID)
}
}
}
// +其他模块playurl
wg.Go(func() error {
otherRoomListPlayURLMap = dao.BvcApi.GetPlayUrlMulti(ctx, otherRoomIDSlice, 0, 4, build, req.Platform)
return nil
})
waitErr := wg.Wait()
if waitErr != nil {
log.Error("[GetAllList]wait error: %s", waitErr)
return
}
// 封装
tagIndex := 0
for index, m := range rawModuleList {
module := m.(map[string]interface{})
moduleInfo := module["module_info"].(map[string]interface{})
moduleList := module["list"].([]interface{})
moduleType := jsonMustInt(moduleInfo["type"], 0)
if moduleType == 0 {
continue
}
// 初始化
resp.ModuleList[index] = make(map[string]interface{})
resp.ModuleList[index]["list"] = moduleList
resp.ModuleList[index]["module_info"] = moduleInfo
if moduleType == _bannerType {
resp.ModuleList[index]["list"] = bannerResp.List
}
if moduleType == _navigatorType && req.Platform == "android" && build <= 5333002 {
// 分区入口5.33版本还返回4个(前3个+全部),5.34透传后台的5个
if len(moduleList) > 3 {
resp.ModuleList[index]["list"] = append(moduleList[:3], map[string]interface{}{
"id": 12,
"pic": "https://i0.hdslb.com/bfs/vc/ff03528785fc8c91491d79e440398484811d6d87.png",
"link": "https://live.bilibili.com/app/mytag/",
"title": "全部标签",
})
}
}
if moduleType == _seaPatrolType {
if seaResp.List != nil {
resp.ModuleList[index]["list"] = seaResp.List
}
if seaResp.ModuleInfo != nil {
resp.ModuleList[index]["module_info"] = seaResp.ModuleInfo
}
if seaResp.ExtraInfo != nil {
resp.ModuleList[index]["extra_info"] = seaResp.ExtraInfo
}
}
if moduleType == _myAreaTagType {
if myTagResp.List != nil {
resp.ModuleList[index]["list"] = myTagResp.List
}
if myTagResp.ModuleInfo != nil {
resp.ModuleList[index]["module_info"] = myTagResp.ModuleInfo
}
if myTagResp.ExtraInfo != nil {
resp.ModuleList[index]["extra_info"] = myTagResp.ExtraInfo
}
}
var isTagGray int
iTmp, _ := myTagResp.ExtraInfo["is_gray"].(int64)
isTagGray = int(iTmp)
// 常用分区房间列表填充
if moduleType == _myAreaTagListType {
if isTagGray == 0 {
continue
}
if len(myTagAreaIds) == 0 || tagIndex >= len(myTagAreaIds) {
continue
}
mTagAreaID := myTagAreaIds[tagIndex]
if _, ok := myTagRoomListMap[mTagAreaID]; ok {
for _, v := range myTagRoomListMap[mTagAreaID] {
if myTagRoomListPlayURLMap[v.Roomid] != nil {
v.AcceptQuality = myTagRoomListPlayURLMap[v.Roomid].AcceptQuality
v.CurrentQuality = myTagRoomListPlayURLMap[v.Roomid].CurrentQuality
v.PlayUrl = myTagRoomListPlayURLMap[v.Roomid].Url["h264"]
v.PlayUrlH265 = myTagRoomListPlayURLMap[v.Roomid].Url["h265"]
}
}
resp.ModuleList[index]["list"] = myTagRoomListMap[mTagAreaID]
if _, ok := myTagAreaInfoMap[mTagAreaID]; ok {
areaInfo := myTagAreaInfoMap[mTagAreaID]
moduleInfo["title"] = areaInfo.Name
moduleInfo["link"] = fmt.Sprintf(_areaModuleLink, areaInfo.ParentId, parentName[areaInfo.ParentId], areaInfo.Id, areaInfo.Name)
resp.ModuleList[index]["module_info"] = moduleInfo
}
}
tagIndex++
}
// 运营推荐分区对常用分区去重
if moduleType == _yunyingRecFormType || moduleType == _yunyingRecSquareType {
link := moduleInfo["link"]
u, err := url.Parse(link.(string))
if err != nil {
log.Warn("[GetAllList]url.Parse (%s) error: %v", link, err)
continue
}
m, err := url.ParseQuery(u.RawQuery)
if err != nil {
log.Warn("[GetAllList]url.ParseQuery (%s) error: %v", link, err)
continue
}
area, ok := m["area_id"]
if !ok {
log.Warn("[GetAllList]url ((%s) area_id lost: %v", link, ok)
continue
}
trueArea, err := strconv.Atoi(area[0])
if err != nil {
log.Warn("[GetAllList]get trueAreaId error: %v", link, ok)
continue
}
if _, ok := myTagRoomListMap[int64(trueArea)]; ok && isTagGray == 1 {
resp.ModuleList[index]["list"] = nil
} else {
for _, v := range moduleList {
if v == nil {
continue
}
vv := v.(map[string]interface{})
roomID := jsonMustInt(vv["roomid"], 0)
if roomID == 0 {
continue
}
if otherRoomListPlayURLMap[roomID] != nil {
vv["accept_quality"] = otherRoomListPlayURLMap[roomID].AcceptQuality
vv["current_quality"] = otherRoomListPlayURLMap[roomID].CurrentQuality
vv["play_url"] = otherRoomListPlayURLMap[roomID].Url["h264"]
vv["play_url_h265"] = otherRoomListPlayURLMap[roomID].Url["h265"]
}
}
resp.ModuleList[index]["list"] = moduleList
resp.ModuleList[index]["module_info"] = moduleInfo
}
}
if moduleType == _feedType {
if attentionResp.ModuleInfo != nil {
resp.ModuleList[index]["module_info"] = attentionResp.ModuleInfo
}
if attentionResp.ExtraInfo != nil {
resp.ModuleList[index]["extra_info"] = attentionResp.ExtraInfo
}
if attentionResp.List != nil {
for _, v := range attentionResp.List.([]interface{}) {
vv := v.(*relationV2.AppLiveHomePageResp_Rooms)
if attentionRoomListPlayURLMap[vv.Roomid] != nil {
vv.AcceptQuality = attentionRoomListPlayURLMap[vv.Roomid].AcceptQuality
vv.CurrentQuality = attentionRoomListPlayURLMap[vv.Roomid].CurrentQuality
vv.PlayUrl = attentionRoomListPlayURLMap[vv.Roomid].Url["h264"]
vv.PlayUrlH265 = attentionRoomListPlayURLMap[vv.Roomid].Url["h265"]
}
}
resp.ModuleList[index]["list"] = attentionResp.List
}
}
if moduleType == _recFormType || moduleType == _recSquareType {
moduleInfo["is_sky_horse_gray"] = isSkyHorseGrayOk
resp.ModuleList[index]["module_info"] = moduleInfo
if loginRecResp.List != nil {
// is uid set
for _, v := range loginRecResp.List.([]map[string]interface{}) {
roomID := int64(0)
r, ok := v["roomid"].(json.Number)
if ok {
rr, intErr := r.Int64()
if intErr != nil {
continue
}
roomID = rr
} else {
roomID = v["roomid"].(int64)
}
if roomID == 0 {
continue
}
if loginRecRoomListPlayURLMap[roomID] != nil {
v["accept_quality"] = loginRecRoomListPlayURLMap[roomID].AcceptQuality
v["current_quality"] = loginRecRoomListPlayURLMap[roomID].CurrentQuality
v["play_url"] = loginRecRoomListPlayURLMap[roomID].Url["h264"]
v["play_url_h265"] = loginRecRoomListPlayURLMap[roomID].Url["h265"]
}
}
resp.ModuleList[index]["list"] = loginRecResp.List
} else {
for _, v := range moduleList {
if v == nil {
continue
}
vv := v.(map[string]interface{})
roomID := jsonMustInt(vv["roomid"], 0)
if roomID == 0 {
continue
}
if otherRoomListPlayURLMap[roomID] != nil {
vv["accept_quality"] = otherRoomListPlayURLMap[roomID].AcceptQuality
vv["current_quality"] = otherRoomListPlayURLMap[roomID].CurrentQuality
vv["play_url"] = otherRoomListPlayURLMap[roomID].Url["h264"]
vv["play_url_h265"] = otherRoomListPlayURLMap[roomID].Url["h265"]
}
}
// 只返24个,新推荐已在上面做处理
if len(moduleList) > _defaultRecNum {
resp.ModuleList[index]["list"] = moduleList[:_defaultRecNum]
} else {
resp.ModuleList[index]["list"] = moduleList
}
}
}
if moduleType == _parentAreaFormType || moduleType == _parentAreaSquareType {
for _, v := range moduleList {
if v == nil {
continue
}
vv := v.(map[string]interface{})
roomID := jsonMustInt(vv["roomid"], 0)
if roomID == 0 {
continue
}
if otherRoomListPlayURLMap[roomID] != nil {
vv["accept_quality"] = otherRoomListPlayURLMap[roomID].AcceptQuality
vv["current_quality"] = otherRoomListPlayURLMap[roomID].CurrentQuality
vv["play_url"] = otherRoomListPlayURLMap[roomID].Url["h264"]
vv["play_url_h265"] = otherRoomListPlayURLMap[roomID].Url["h265"]
}
}
resp.ModuleList[index]["list"] = moduleList
}
}
ret = resp
return
}
func jsonMustInt(arg interface{}, def int64) int64 {
if arg == nil {
log.Warn("jsonMustInt arg(%v) nil!", arg)
return def
}
r, ok := arg.(json.Number)
if !ok {
log.Warn("jsonMustInt arg(%v) is not json.Number but %v", arg, reflect.TypeOf(arg))
return def
}
rr, err := r.Int64()
if err != nil {
log.Warn("jsonMustInt arg(%v) transfer error: %v", arg, err)
return def
}
return rr
}
// Change implementation
// 首页换一换接口 for 天马
func (s *Service) Change(ctx context.Context, req *v1indexpb.ChangeReq) (resp *v1indexpb.ChangeResp, err error) {
resp = &v1indexpb.ChangeResp{
ModuleList: make([]*v1indexpb.ChangeResp_ModuleList, 0),
}
mid, isUIDSet := metadata.Value(ctx, metadata.Mid).(int64)
var uid int64
if isUIDSet {
uid = mid
}
// deviceInterface, _ := ctx.Get("device")
// device := req.Device
duplicates, _ := xstr.SplitInts(req.AttentionRoomId)
duplicatesMap := make(map[int64]bool)
for _, roomID := range duplicates {
duplicatesMap[roomID] = true
}
build := req.Build
buvid := ""
// 主站封好的,可从device里获取到sid、buvid、buvid3、build、channel、device、mobi_app、platform
device, ok := metadata.Value(ctx, metadata.Device).(*blademaster.Device)
if ok {
buvid = device.Buvid
}
var recModuleInfo *v1indexpb.ChangeResp_ModuleInfo
allListOut, callErr := dao.RoomApi.V2AppIndex.GetAllList(rpcCtx.WithTimeout(ctx, 100*time.Millisecond), &roomV2.AppIndexGetAllListReq{
Platform: req.Platform,
Device: req.Device,
Scale: req.Scale,
Build: int64(build),
ModuleId: req.ModuleId,
})
if callErr != nil {
log.Error("[Change]get all list rpc error, room.v2.AppIndex.setAllList, error:%+v", callErr)
err = errors.WithMessage(ecode.ChangeGetAllListRPCError, "CHANGE GET ALL LIST FAIL#1")
return
}
if allListOut.Code != 0 || allListOut.Data == nil {
log.Error("[Change]get all list return data error, code, %d, msg: %s, error:%+v", allListOut.Code, allListOut.Msg, err)
err = errors.WithMessage(ecode.ChangeGetAllListReturnError, "CHANGE GET ALL LIST FAIL#2")
return
}
if len(allListOut.Data.ModuleList) == 0 {
log.Error("[Change]get all list return empty, code, %d, msg: %s, error:%+v", allListOut.Code, allListOut.Msg, err)
err = errors.WithMessage(ecode.ChangeGetAllListEmptyError, "CHANGE GET ALL LIST FAIL#3")
return
}
m := allListOut.Data.ModuleList[0]
duplicateList := make([]*roomV2.AppIndexGetAllListResp_RoomList, 0)
for _, itemInfo := range m.List {
if _, ok := duplicatesMap[itemInfo.Roomid]; !ok {
duplicateList = append(duplicateList, itemInfo)
}
}
m.List = duplicateList
recModuleInfo = &v1indexpb.ChangeResp_ModuleInfo{
Id: m.ModuleInfo.Id,
Title: m.ModuleInfo.Title,
Pic: m.ModuleInfo.Pic,
Type: m.ModuleInfo.Type,
Link: m.ModuleInfo.Link,
Count: m.ModuleInfo.Count,
IsSkyHorseGray: 0,
}
// 目前只有推荐-天马有换一换,都必须有登陆态
roomIds := make([]int64, 0)
list := make([]*v1indexpb.ChangeResp_List, 0)
for i, itemInfo := range m.List {
if i >= 24 {
break
}
roomIds = append(roomIds, itemInfo.Roomid)
list = append(list, &v1indexpb.ChangeResp_List{
Roomid: itemInfo.Roomid,
Title: itemInfo.Title,
Uname: itemInfo.Uname,
Online: itemInfo.Online,
Cover: itemInfo.Cover,
Link: "/" + strconv.Itoa(int(itemInfo.Roomid)),
Face: itemInfo.Face,
AreaV2ParentId: itemInfo.AreaV2ParentId,
AreaV2ParentName: itemInfo.AreaV2ParentName,
AreaV2Id: itemInfo.AreaV2Id,
AreaV2Name: itemInfo.AreaV2Name,
BroadcastType: itemInfo.BroadcastType,
PendentRu: itemInfo.PendentRu,
PendentRuPic: itemInfo.PendentRuPic,
PendentRuColor: itemInfo.PendentRuColor,
RecType: itemInfo.RecType,
CurrentQuality: itemInfo.CurrentQuality,
AcceptQuality: itemInfo.AcceptQuality,
PlayUrl: itemInfo.PlayUrl,
})
}
resp.ModuleList = append(resp.ModuleList, &v1indexpb.ChangeResp_ModuleList{
List: list,
ModuleInfo: recModuleInfo,
})
isOpen := conf.Conf.SkyHorseStatus
if isOpen && isUIDSet && s.isSkyHorseRec(uid) {
recPage := rand.Intn(4)
if recPage == 1 || recPage == 0 {
recPage = 2
}
recList, skyHorseErr := getSkyHorseRoomList(ctx, uid, buvid, req.Build, req.Platform, duplicates, int64(recPage))
if skyHorseErr != nil {
log.Error("[Change]getSkyHorseRoomList error:%+v", skyHorseErr)
// err = errors.WithMessage(ecode.SkyHorseError, "")
} else if len(recList) <= 0 {
log.Error("[Change]getSkyHorseRoomList empty:%+v", recList)
// err = errors.WithMessage(ecode.ChangeSkyHorseEmptyError, "")
} else {
list := make([]*v1indexpb.ChangeResp_List, 0)
for i, recInfo := range recList {
if i >= 6 {
continue
}
roomIds = append(roomIds, recInfo.RoomId)
list = append(list, &v1indexpb.ChangeResp_List{
Roomid: recInfo.RoomId,
Title: recInfo.Title,
Uname: recInfo.Uname,
Online: recInfo.Online,
Cover: recInfo.Cover,
Link: "/" + strconv.Itoa(int(recInfo.RoomId)),
Face: recInfo.Face,
AreaV2ParentId: recInfo.AreaV2ParentId,
AreaV2ParentName: recInfo.AreaV2ParentName,
AreaV2Id: recInfo.AreaV2Id,
AreaV2Name: recInfo.AreaV2Name,
BroadcastType: recInfo.BroadcastType,
PendentRu: recInfo.PendentRu,
PendentRuPic: recInfo.PendentRuPic,
PendentRuColor: recInfo.PendentRuColor,
RecType: _recTypeSkyHorse,
})
}
skyHorseList := make([]*v1indexpb.ChangeResp_ModuleList, 0)
recModuleInfo.IsSkyHorseGray = 1
skyHorseList = append(skyHorseList, &v1indexpb.ChangeResp_ModuleList{
List: list,
ModuleInfo: recModuleInfo,
})
resp.ModuleList = skyHorseList
}
}
changeRoomListPlayURLMap := dao.BvcApi.GetPlayUrlMulti(ctx, roomIds, 0, 4, build, req.Platform)
for _, v := range resp.ModuleList[0].List {
if changeRoomListPlayURLMap[v.Roomid] != nil {
v.AcceptQuality = changeRoomListPlayURLMap[v.Roomid].AcceptQuality
v.CurrentQuality = changeRoomListPlayURLMap[v.Roomid].CurrentQuality
v.PlayUrl = changeRoomListPlayURLMap[v.Roomid].Url["h264"]
v.PlayUrlH265 = changeRoomListPlayURLMap[v.Roomid].Url["h265"]
}
}
// 赋值
return
}
// 获取天马房间信息列表
// 已将强推roomids传给天马,其他的可通过传duplicates来merge进去
func getSkyHorseRoomList(ctx context.Context, uid int64, buvid string, build int64, platform string, duplicates []int64, recPage int64) (resp []*roomItem, err error) {
clientRecStrongTimeout := time.Duration(conf.GetTimeout("clientRecStrong", 100)) * time.Millisecond
strongRecList, strongRecErr := dao.RoomApi.V1RoomRecommend.ClientRecStrong(rpcCtx.WithTimeout(ctx, clientRecStrongTimeout), &roomV1.RoomRecommendClientRecStrongReq{RecPage: recPage})
// liverpc.NewClient().CallRaw()
recDuplicate := make([]int64, 0)
if strongRecErr != nil {
log.Error("[getSkyHorseRoomList]room.v1.ClientRecStrong rpc error:%+v", strongRecErr)
} else if strongRecList.Code != 0 {
log.Error("[getSkyHorseRoomList]room.v1.ClientRecStrong response error:%+v,code:%d,msg:%s", strongRecErr, strongRecList.Code, strongRecList.Msg)
} else {
for _, strongInfo := range strongRecList.Data.Result {
if strongInfo.Roomid == 0 {
continue
}
recDuplicate = append(recDuplicate, strongInfo.Roomid)
}
}
strongLen := len(recDuplicate)
duplicates = append(duplicates, recDuplicate...)
skyHorseRec, skyHorseErr := dao.SkyHorseApi.GetSkyHorseRec(ctx, uid, buvid, build, platform, duplicates, strongLen, _skyHorseRecTimeOut)
if skyHorseErr != nil {
err = errors.WithMessage(ecode.SkyHorseError, "")
return
}
roomIds := make([]int64, 0)
for _, skyHorseInfo := range skyHorseRec.Data {
roomIds = append(roomIds, int64(skyHorseInfo.Id))
}
indexRoomListFields := []string{
"roomid",
"title",
"uname",
"online",
"cover",
"user_cover",
"link",
"face",
"area_v2_parent_id",
"area_v2_parent_name",
"area_v2_id",
"area_v2_name",
"broadcast_type",
"uid",
}
wg, _ := errgroup.WithContext(ctx)
// 房间基础信息(是map,但是天马返回是无序的)
var multiRoomListResp *roomV2.RoomGetByIdsResp
wg.Go(func() error {
getByIdsTimeout := time.Duration(conf.GetTimeout("getByIds", 50)) * time.Millisecond
multiRoomList, getByIdsError := dao.RoomApi.V2Room.GetByIds(rpcCtx.WithTimeout(ctx, getByIdsTimeout), &roomV2.RoomGetByIdsReq{
Ids: roomIds,
NeedBroadcastType: 1,
NeedUinfo: 1,
Fields: indexRoomListFields,
From: "app-interface.gateway",
})
if getByIdsError != nil {
log.Error("[getSkyHorseRoomList]room.v2.getByIds rpc error:%+v", getByIdsError)
// 这个是推荐房间列表的基础信息,如果失败需要cancel,不然返回值会很奇怪
return errors.WithMessage(ecode.GetRoomError, "room.v2.getByIds rpc error")
}
if multiRoomList.Code != 0 {
log.Error("[getSkyHorseRoomList]room.v2.getByIds response error:%+v,code:%d,msg:%s", getByIdsError, multiRoomList.Code, multiRoomList.Msg)
// 这个是推荐房间列表的基础信息,如果失败需要cancel,不然返回值会很奇怪
return errors.WithMessage(ecode.GetRoomError, "room.v2.getByIds response error")
}
multiRoomListResp = multiRoomList
return nil
})
// 房间角标信息
pendantRoomListResp := &roomV1.RoomPendantGetPendantByIdsResp{}
wg.Go(func() error {
getPendantByIdsTimeout := time.Duration(conf.GetTimeout("getPendantByIds", 50)) * time.Millisecond
pendantRoomList, getPendantError := dao.RoomApi.V1RoomPendant.GetPendantByIds(rpcCtx.WithTimeout(ctx, getPendantByIdsTimeout), &roomV1.RoomPendantGetPendantByIdsReq{
Ids: roomIds,
Type: "mobile_index_badge",
Position: 2, // 历史原因,取右上,但客户端展示在左上
})
if getPendantError != nil {
log.Error("[getSkyHorseRoomList]room.v1.getPendantByIds rpc error:%+v", getPendantError)
return nil
}
if pendantRoomList.Code != 0 {
log.Error("[getSkyHorseRoomList]room.v1.getPendantByIds response error:%+v,code:%d,msg:%s", getPendantError, pendantRoomList.Code, pendantRoomList.Msg)
return nil
}
pendantRoomListResp = pendantRoomList
return nil
})
waitErr := wg.Wait()
if waitErr != nil {
log.Error("[getSkyHorseRoomList]wait error(%+v)", waitErr)
return
}
pendantResult := make(map[int64]*roomV1.RoomPendantGetPendantByIdsResp_Result)
// 天马返回是无序的
if multiRoomListResp == nil {
err = errors.WithMessage(ecode.GetRoomEmptyError, "")
return
}
respSlice := make([]*roomV2.RoomGetByIdsResp_RoomInfo, 0)
for _, roomBaseInfo := range multiRoomListResp.Data {
respSlice = append(respSlice, roomBaseInfo)
}
for i := 0; i < 6; i++ {
if strongRecList != nil && strongRecList.Data != nil && strongRecList.Data.Result != nil {
if recInfo, ok := strongRecList.Data.Result[int64(i)]; ok {
resp = append(resp, &roomItem{
RoomId: recInfo.Roomid,
Title: recInfo.Title,
Uname: recInfo.Uname,
Online: recInfo.Online,
Cover: recInfo.Cover,
Link: "/" + strconv.Itoa(int(recInfo.Roomid)),
Face: recInfo.Face,
AreaV2ParentId: recInfo.AreaV2ParentId,
AreaV2ParentName: recInfo.AreaV2ParentName,
AreaV2Id: recInfo.AreaV2Id,
AreaV2Name: recInfo.AreaV2Name,
BroadcastType: recInfo.BroadcastType,
PendentRu: recInfo.PendentRu,
PendentRuPic: recInfo.PendentRuPic,
PendentRuColor: recInfo.PendentRuColor,
RecType: _recTypeForce,
CurrentQuality: recInfo.CurrentQuality,
AcceptQuality: recInfo.AcceptQuality,
})
continue
}
}
if len(respSlice) <= 0 {
continue
}
tmpItem := respSlice[0:1][0]
respSlice = respSlice[1:]
pendantValue := ""
pendantBgPic := ""
pendantBgColor := ""
if pendantRoomListResp != nil && pendantRoomListResp.Data != nil {
pendantResult = pendantRoomListResp.Data.Result
if pendantResult[tmpItem.Roomid] != nil {
// 移动端取value, web取name
pendantValue = pendantResult[tmpItem.Roomid].Value
pendantBgPic = pendantResult[tmpItem.Roomid].BgPic
if pendantResult[tmpItem.Roomid].BgColor != "" {
pendantBgColor = pendantResult[tmpItem.Roomid].BgColor
} else {
pendantBgColor = _mobileIndexBadgeColorDefault
}
}
}
cover := ""
if tmpItem.UserCover != "" {
cover = tmpItem.UserCover
} else {
cover = tmpItem.Cover
}
resp = append(resp, &roomItem{
RoomId: tmpItem.Roomid,
Title: tmpItem.Title,
Uname: tmpItem.Uname,
Online: tmpItem.Online,
Cover: cover,
Link: "/" + strconv.Itoa(int(tmpItem.Roomid)),
Face: tmpItem.Face,
AreaV2ParentId: tmpItem.AreaV2ParentId,
AreaV2ParentName: tmpItem.AreaV2ParentName,
AreaV2Id: tmpItem.AreaV2Id,
AreaV2Name: tmpItem.AreaV2Name,
BroadcastType: tmpItem.BroadcastType,
PendentRu: pendantValue,
PendentRuPic: pendantBgPic,
PendentRuColor: pendantBgColor,
RecType: _recTypeSkyHorse,
})
}
return
}
func (s *Service) isSkyHorseRec(mid int64) bool {
lastMid := strconv.Itoa(int(mid % 100))
if len(lastMid) < 2 {
lastMid = "0" + lastMid
}
_, isSkyHorseGray := s.conf.SkyHorseGray[lastMid]
return isSkyHorseGray
}
func (s *Service) getAllList(ctx context.Context) (json.RawMessage, error) {
allListOut, err := dao.RoomRawApi.CallRaw(ctx, 2,
"AppIndex.getAllRawList", &liverpc.Args{})
if err != nil {
log.Error("[getAllList]get all list rpc error, room.v2.AppIndex.getAllRawList, error:%+v", err)
err = errors.WithMessage(ecode.GetAllListRPCError, "GET ALL LIST FAIL#1")
return json.RawMessage{}, err
}
if allListOut == nil {
log.Error("[getAllList]get all list raw data nil, room.v2.AppIndex.getAllRawList")
err = errors.WithMessage(ecode.GetAllListRPCError, "GET ALL LIST FAIL#2")
return json.RawMessage{}, err
}
if allListOut.Code != 0 || allListOut.Data == nil {
log.Error("[getAllList]get all list return data error, code, %d, msg: %s, error:%+v", allListOut.Code, allListOut.Message, err)
err = errors.WithMessage(ecode.GetAllListReturnError, "GET ALL LIST FAIL#3")
return json.RawMessage{}, err
}
allListJSONObj, jsonErr := simplejson.NewJson(allListOut.Data)
if jsonErr != nil {
log.Error("[getAllList]get all list simplejson error, error:%+v", err)
err = errors.WithMessage(ecode.GetAllListReturnError, "GET ALL LIST FAIL#4")
return json.RawMessage{}, err
}
allListCache := allListJSONObj.Get("module_list").MustArray()
if len(allListCache) > 1 && allListCache[1] == nil {
log.Error("[getAllList]abnormal module, allListCache:%+v", allListCache)
err = errors.WithMessage(ecode.GetAllListReturnError, "GET ALL LIST FAIL#5")
return json.RawMessage{}, err
}
return allListOut.Data, nil
}
func (s *Service) tickCacheAllList(ctx context.Context) {
ticker := time.NewTicker(5 * time.Second)
for {
select {
case <-ticker.C:
allListData, err := s.getAllList(ctx)
if err != nil {
log.Error("[tickCacheAllList] setAllList error(%+v)", err)
continue
}
if len(allListData) <= 0 {
log.Error("[tickCacheAllList] setAllList empty data(%+v)", allListData)
continue
}
log.Info("[tickCacheAllList] setAllList success!")
s.allListInfo.Store(allListData)
}
}
}
func (s *Service) getAllListFromCache(ctx context.Context) (allListCache []interface{}) {
allListRawCache := s.allListInfo.Load()
if allListRawCache == nil {
log.Warn("[getAllListFromCache] cache miss!")
allList, err := s.getAllList(ctx)
if err != nil {
log.Error("[getAllListFromCache] pass through error(%+v)", err)
}
allListRawCache = allList
}
allListJSONObj, err := simplejson.NewJson(allListRawCache.(json.RawMessage))
if err != nil {
log.Error("[getAllListFromCache]get all list simplejson error, error:%+v", err)
return
}
allListCache = allListJSONObj.Get("module_list").MustArray()
if allListCache[1] == nil {
fmt.Printf("abnormal module, allListRawCache: %+v, module_list: %+v", allListRawCache, allListJSONObj.Get("module_list"))
}
log.Info("[getAllListFromCache] cache hit! len: %d", len(allListCache))
return
}