1232 lines
36 KiB
Go
1232 lines
36 KiB
Go
package dao
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"time"
|
||
|
||
"go-common/app/service/live/dao-anchor/model"
|
||
|
||
v1pb "go-common/app/service/live/dao-anchor/api/grpc/v1"
|
||
"go-common/library/ecode"
|
||
"go-common/library/log"
|
||
|
||
"github.com/pkg/errors"
|
||
)
|
||
|
||
//房間狀態常量
|
||
const (
|
||
LIVE_OPEN = 1
|
||
LIVE_CLOSE = 0
|
||
LIVE_ROUND = 2
|
||
)
|
||
|
||
//attr表相关常量定义
|
||
const (
|
||
ATTRID_POPULARITY = 1
|
||
ATTRID_REVENUE = 2
|
||
ATTRID_DANMU = 3
|
||
ATTRID_RANK_LIST = 4
|
||
ATTRID_VALID_LIVE_DAYS = 5
|
||
)
|
||
|
||
const (
|
||
//ATTRSUBID_RANK_HOUR 小时榜
|
||
ATTRSUBID_RANK_HOUR = 1
|
||
)
|
||
const (
|
||
//ATTRSUBID_POPULARITY_REALTIME 实时人气值
|
||
ATTRSUBID_POPULARITY_REALTIME = 1
|
||
//ATTRSUBID_POPULARITY_MAX_TO_ARG_7 7日人气峰值的均值
|
||
ATTRSUBID_POPULARITY_MAX_TO_ARG_7 = 2
|
||
//ATTRSUBID_POPULARITY_MAX_TO_ARG_30 30日人气峰值的均值
|
||
ATTRSUBID_POPULARITY_MAX_TO_ARG_30 = 3
|
||
)
|
||
const (
|
||
//ATTRSUBID_REVENUE_MINUTE_NUM_15 15分钟营收
|
||
ATTRSUBID_REVENUE_MINUTE_NUM_15 = 1
|
||
//ATTRSUBID_REVENUE_MINUTE_NUM_30 30分钟营收
|
||
ATTRSUBID_REVENUE_MINUTE_NUM_30 = 2
|
||
//ATTRSUBID_REVENUE_MINUTE_NUM_45 45分钟营收
|
||
ATTRSUBID_REVENUE_MINUTE_NUM_45 = 3
|
||
//ATTRSUBID_REVENUE_MINUTE_NUM_60 60分钟营收
|
||
ATTRSUBID_REVENUE_MINUTE_NUM_60 = 4
|
||
)
|
||
const (
|
||
//ATTRSUBID_DANMU_MINUTE_NUM_15 15分钟弹幕
|
||
ATTRSUBID_DANMU_MINUTE_NUM_15 = 1
|
||
//ATTRSUBID_DANMU_MINUTE_NUM_30 30分钟弹幕
|
||
ATTRSUBID_DANMU_MINUTE_NUM_30 = 2
|
||
//ATTRSUBID_DANMU_MINUTE_NUM_45 45分钟弹幕
|
||
ATTRSUBID_DANMU_MINUTE_NUM_45 = 3
|
||
//ATTRSUBID_DANMU_MINUTE_NUM_60 60分钟弹幕
|
||
ATTRSUBID_DANMU_MINUTE_NUM_60 = 4
|
||
)
|
||
|
||
//有效开播天数
|
||
const (
|
||
VALID_LIVE_DAYS_TYPE_1 = 1 //一次开播大于5分钟
|
||
VALID_LIVE_DAYS_TYPE_2 = 2 // 累加大于等于120分钟
|
||
)
|
||
const (
|
||
//ATTRSUBID_VALID_LIVE_DAYS_TYPE_1_DAY_7 近7天的有效天数,(有效天数:一次开播大于5分钟)
|
||
ATTRSUBID_VALID_LIVE_DAYS_TYPE_1_DAY_7 = 1
|
||
//ATTRSUBID_VALID_LIVE_DAYS_TYPE_1_DAY_14 近14天的有效天数,(有效天数:一次开播大于5分钟)
|
||
ATTRSUBID_VALID_LIVE_DAYS_TYPE_1_DAY_14 = 2
|
||
//ATTRSUBID_VALID_LIVE_DAYS_TYPE_2_DAY_7 近7天的有效天数,(有效天数:累加大于等于120分钟)
|
||
ATTRSUBID_VALID_LIVE_DAYS_TYPE_2_DAY_7 = 3
|
||
//ATTRSUBID_VALID_LIVE_DAYS_TYPE_2_DAY_30 近30天的有效天数,(有效天数:累加大于等于120分钟)
|
||
ATTRSUBID_VALID_LIVE_DAYS_TYPE_2_DAY_30 = 4
|
||
)
|
||
|
||
//tag表相关常量定义
|
||
const (
|
||
TAGID_PK = 1
|
||
TAGID_LOTTERY = 2
|
||
ROOM_EXT_SHARDING = 10
|
||
|
||
EXP_2_SCORE_RATE = 100
|
||
)
|
||
|
||
const (
|
||
_roomTable = "room"
|
||
_roomExtTablePrefix = "room_extend"
|
||
_anchorTable = "anchor"
|
||
_tagTable = "tag"
|
||
_attrTable = "attr"
|
||
|
||
_shortTable = "ap_short_room"
|
||
_subAreaTable = "ap_room_area_v2"
|
||
|
||
// add room info
|
||
_addRoomInfo1 = "insert into `%s` (`uid`) values (?)"
|
||
// add room info
|
||
_addRoomInfo2 = "insert into `%s` (`uid`,`room_id`) values (?,?)"
|
||
|
||
// add room extend info
|
||
_addRoomExtInfo = "insert into `%s_%d` (`room_id`) values (?)"
|
||
|
||
// add anchor info
|
||
_addAnchorInfo = "insert into `%s` (`uid`,`room_id`,`san_score`) values (?,?,12)"
|
||
|
||
// update room info
|
||
_updateRoomInfo = "update `%s` set %s where `room_id`=?"
|
||
// update room extend info
|
||
_updateRoomExtInfo = "update `%s_%d` set %s where `room_id`=?"
|
||
// update anchor info
|
||
_updateAnchorInfo = "update `%s` set %s where `uid`=?"
|
||
// tag create info
|
||
_tagCreateInfo = "insert ignore into `%s` (`room_id`,`tag_id`,`tag_sub_id`,`tag_value`,`tag_ext`,`tag_expire_at`) values (?,?,?,?,?,?) on duplicate key update `tag_value`=?,`tag_ext`=?,`tag_expire_at`=?"
|
||
// attr create info
|
||
_attrCreateInfo = "insert ignore into `%s` (`room_id`,`attr_id`,`attr_sub_id`,`attr_value`,`attr_ext`) values (?,?,?,?,?) on duplicate key update `attr_value`=?,`attr_ext`=?"
|
||
// attr set ex info
|
||
_attrSetRoomId = "update `%s` set `room_id`=? where `attr_id`=? and `attr_sub_id`=? and `attr_value`=?"
|
||
// attr set ex info
|
||
_attrSetValue = "update `%s` set `attr_value`=? where `room_id`=? and `attr_id`=? and `attr_sub_id`=?"
|
||
// attr select room_id
|
||
_attrSelectRoomId = "select `room_id` from `%s` where `attr_id`=? and `attr_sub_id`=? and `attr_value`=?"
|
||
//
|
||
_attrSelectValue = "select `attr_value` from `%s` where `room_id`=? and `attr_id`=? and `attr_sub_id`=?"
|
||
// query online room info
|
||
_queryOnlineRoomInfo = "select `room_id`,`uid`,`title`,`description`,`tags`,`background`,`cover`,`lock_status`,`lock_time`,`hidden_time`,`record_switch`,`round_switch`,`live_start_time`,`live_screen_type`,`live_area_id`,`live_area_parent_id`,`live_type` from `room` where `live_start_time`!=0 order by `room_id` limit ?,?"
|
||
// TODO 在播房间是否要处理轮播场景
|
||
// query online room by area info
|
||
_queryOnlineRoomByAreaInfo = "select `room_id` from `room` where `live_start_time`!=0 %s order by `live_start_time` desc"
|
||
_queryOnlineRoomByAreaCond = "and (`live_area_id`=%d or `live_area_parent_id`=%d)"
|
||
|
||
// query room info
|
||
_queryRoomInfo = "select `room_id`,`uid`,`title`,`description`,`tags`,`background`,`cover`,`lock_status`,`lock_time`,`hidden_time`,`record_switch`,`round_switch`,`live_start_time`,`live_screen_type`,`live_area_id`,`live_area_parent_id`,`live_type` from `room` where `room_id` in (%s)"
|
||
// query anchor info
|
||
_queryAnchorInfo = "select `room_id`,`san_score`,`profile_type`,`round_status`,`record_status`,`exp` from `%s` where `uid` in (%s)"
|
||
// query tag info
|
||
_queryTagInfo = "select `room_id`,`tag_id`,`tag_sub_id`,`tag_value`,`tag_ext`,`tag_expire_at` from `%s` where `room_id` in (%s) and `tag_expire_at`>?"
|
||
// query room ext info
|
||
_queryRoomExtInfo = "select `room_id`,`keyframe`,`popularity_count` from `%s_%d` where `room_id` in (%s)"
|
||
|
||
// get parent area id
|
||
_queryParentAreaID = "select `parent_id` from `%s` where `id`=?"
|
||
// get short id
|
||
_queryShortID = "select `short_id`,`roomid` from `%s` where `roomid` in (%s)"
|
||
|
||
// filter out short room-id and its corresponding room-id
|
||
_filterShortID = "select `short_id`,`roomid` from `%s` where `short_id` in (%s) and `status`=1"
|
||
|
||
// query attr info
|
||
_queryAttrInfo = "select `room_id`,`attr_value` from `%s` where `attr_id`=? and `attr_sub_id`=? and `room_id` in (%s)"
|
||
|
||
// query attr info
|
||
_queryAttrInfo2 = "select `room_id`,`attr_sub_id`,`attr_value` from `%s` where `attr_id`=? order by `attr_sub_id`"
|
||
|
||
// delete attr info
|
||
_deleteAttrInfo = "delete from `%s` where `attr_id`=? and `attr_sub_id`=?"
|
||
|
||
// query area info
|
||
_queryAreaInfo = "select `id`,`name`,`parent_id` from `%s` where `id`=?"
|
||
|
||
// query sub-areas for a given area
|
||
_querySubAreaInfo = "select `id`,`name` from `%s` where `parent_id`=?"
|
||
)
|
||
|
||
// Turns short-id, if any, into room-id
|
||
func (d *Dao) dbNormalizeRoomIDs(ctx context.Context, roomIDs []int64) (resp []int64, err error) {
|
||
if len(roomIDs) <= 0 {
|
||
return
|
||
}
|
||
|
||
resp = make([]int64, len(roomIDs))
|
||
|
||
// Resort to cache first, and for miss roomid, we save pair (roomid, index) to preserve order
|
||
// of our final result
|
||
agnosticRoomIds := make(map[int64]int)
|
||
for i, roomID := range roomIDs {
|
||
xid, ok := d.shortIDMapping.Get(fmt.Sprintf("%d", roomID))
|
||
if ok {
|
||
resp[i] = xid.(int64)
|
||
} else {
|
||
agnosticRoomIds[roomID] = i
|
||
}
|
||
}
|
||
|
||
// We are done.
|
||
if len(agnosticRoomIds) <= 0 {
|
||
return
|
||
}
|
||
|
||
var queryValues string
|
||
for roomID := range agnosticRoomIds {
|
||
if len(queryValues) > 0 {
|
||
queryValues += ","
|
||
}
|
||
queryValues += fmt.Sprintf("%d", roomID)
|
||
}
|
||
|
||
sql := fmt.Sprintf(_filterShortID, _shortTable, queryValues)
|
||
rows, err := d.dbLiveApp.Query(ctx, sql)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbNormalizeRoomIDs] query short id record error(%v), sql(%s)", err, sql)
|
||
return nil, err
|
||
}
|
||
|
||
defer rows.Close()
|
||
|
||
shortIDMapping := make(map[int64]int64)
|
||
for rows.Next() {
|
||
var shortID int64
|
||
var roomID int64
|
||
err = rows.Scan(&shortID, &roomID)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbNormalizeRoomIDs] scan short id record error(%v), roomIDs(%v)",
|
||
err, roomIDs)
|
||
return nil, err
|
||
}
|
||
|
||
shortIDMapping[shortID] = roomID
|
||
}
|
||
|
||
for roomID, index := range agnosticRoomIds {
|
||
xid, ok := shortIDMapping[roomID]
|
||
if ok {
|
||
resp[index] = xid
|
||
d.shortIDMapping.Put(fmt.Sprintf("%d", roomID), xid)
|
||
} else {
|
||
resp[index] = roomID
|
||
d.shortIDMapping.Put(fmt.Sprintf("%d", roomID), roomID)
|
||
}
|
||
}
|
||
|
||
return
|
||
}
|
||
|
||
func (d *Dao) dbDealWithStatus(ctx context.Context, data *v1pb.RoomData) (err error) {
|
||
if data == nil {
|
||
return
|
||
}
|
||
|
||
// 处理开播状态
|
||
if data.LiveStartTime > 0 {
|
||
// 如果开播
|
||
data.LiveStatus = LIVE_OPEN
|
||
} else if data.AnchorRoundSwitch == 1 {
|
||
// 如果轮播
|
||
data.LiveStatus = LIVE_ROUND
|
||
} else {
|
||
data.LiveStatus = LIVE_CLOSE
|
||
}
|
||
|
||
// 处理隐藏状态
|
||
if data.HiddenTime > time.Now().Unix() {
|
||
data.HiddenStatus = 1
|
||
}
|
||
|
||
// 获取分区名称
|
||
areaInfo := &model.AreaInfo{}
|
||
if data.AreaId > 0 {
|
||
areaInfo, err = d.dbFetchAreaInfo(ctx, data.AreaId)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbDealWithStatus] fetch area info error(%v), data(%v), areaid(%v)", err, data, data.AreaId)
|
||
return
|
||
}
|
||
data.AreaName = areaInfo.AreaName
|
||
}
|
||
|
||
if areaInfo.ParentAreaID > 0 {
|
||
areaInfo, err = d.dbFetchAreaInfo(ctx, areaInfo.ParentAreaID)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbDealWithStatus] fetch area info error(%v), data(%v), parent areaid(%v)", err, data, areaInfo.ParentAreaID)
|
||
return
|
||
}
|
||
data.ParentAreaName = areaInfo.AreaName
|
||
}
|
||
return
|
||
}
|
||
|
||
// dbFetchRoomIDByUID implementation
|
||
// dbFetchRoomIDByUID 查询主播房间号
|
||
func (d *Dao) dbFetchRoomIDByUID(ctx context.Context, uid int64) (roomID int64) {
|
||
uids := []int64{uid}
|
||
res := make(map[int64]*v1pb.RoomData)
|
||
|
||
err := d.dbFetchAnchorInfo(ctx, uids, res, false)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomIDByUID] get room ID error(%v), uid(%v)", err, uid)
|
||
return
|
||
}
|
||
|
||
if len(res) <= 1 {
|
||
return
|
||
}
|
||
|
||
for _, v := range res {
|
||
if v.Uid == uid {
|
||
roomID = v.RoomId
|
||
}
|
||
}
|
||
|
||
return
|
||
}
|
||
|
||
// dbFetchAreaInfo implementation
|
||
// dbFetchAreaInfo 查询分区信息
|
||
func (d *Dao) dbFetchAreaInfo(ctx context.Context, areaID int64) (info *model.AreaInfo, err error) {
|
||
if areaID <= 0 {
|
||
return
|
||
}
|
||
key := fmt.Sprintf("%d", areaID)
|
||
res, ok := d.areaInfoMapping.Get(key)
|
||
if ok {
|
||
return res.(*model.AreaInfo), nil
|
||
}
|
||
info = &model.AreaInfo{}
|
||
sql := fmt.Sprintf(_queryAreaInfo, _subAreaTable)
|
||
err = d.dbLiveApp.QueryRow(ctx, sql, areaID).Scan(&info.AreaID, &info.AreaName, &info.ParentAreaID)
|
||
if err == nil {
|
||
d.areaInfoMapping.Put(key, info)
|
||
} else {
|
||
// 尝试从配置中心拿到一级分区名称
|
||
if confInfo, ok := d.c.FirstAreas[key]; ok {
|
||
info.AreaID = areaID
|
||
info.AreaName = confInfo.Name
|
||
info.ParentAreaID = 0
|
||
err = nil
|
||
}
|
||
}
|
||
return
|
||
}
|
||
|
||
func (d *Dao) dbFetchAnchorInfo(ctx context.Context, uids []int64, resp map[int64]*v1pb.RoomData, overwrite bool) (err error) {
|
||
if len(uids) <= 0 {
|
||
return
|
||
}
|
||
|
||
valueList := ""
|
||
for i, id := range uids {
|
||
if i > 0 {
|
||
valueList += ","
|
||
}
|
||
valueList += fmt.Sprintf("%d", id)
|
||
}
|
||
|
||
sql := fmt.Sprintf(_queryAnchorInfo, _anchorTable, valueList)
|
||
rows, err := d.db.Query(ctx, sql)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomByIDs] get anchor record error(%v), uids(%v)", err, uids)
|
||
return err
|
||
}
|
||
|
||
defer rows.Close()
|
||
|
||
for rows.Next() {
|
||
data := &v1pb.RoomData{
|
||
AnchorLevel: new(v1pb.AnchorLevel),
|
||
}
|
||
var exp int64
|
||
err = rows.Scan(&data.RoomId, &data.AnchorSan, &data.AnchorProfileType, &data.AnchorRoundStatus, &data.AnchorRecordStatus, &exp)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomByIDs] scan anchor record error(%v), uids(%v)", err, uids)
|
||
return err
|
||
}
|
||
|
||
data.AnchorLevel.Score = exp / EXP_2_SCORE_RATE
|
||
|
||
data.AnchorLevel.Level, err = model.GetAnchorLevel(data.AnchorLevel.Score)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomByIDs] Failed to get anchor level (%v), level(%d)", err, data.AnchorLevel.Score)
|
||
return err
|
||
}
|
||
|
||
data.AnchorLevel.Left, data.AnchorLevel.Right, err = model.GetLevelScoreInfo(data.AnchorLevel.Level)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomByIDs] Failed to get anchor level score (%v), level(%d)", err, data.AnchorLevel.Level)
|
||
return err
|
||
}
|
||
|
||
data.AnchorLevel.Color, err = model.GetAnchorLevelColor(data.AnchorLevel.Level)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomByIDs] Failed to get anchor level color (%v), level(%d)", err, data.AnchorLevel.Level)
|
||
return err
|
||
}
|
||
|
||
data.AnchorLevel.MaxLevel = model.MaxAnchorLevel
|
||
|
||
if overwrite {
|
||
d := resp[data.RoomId]
|
||
d.AnchorSan = data.AnchorSan
|
||
d.AnchorProfileType = data.AnchorProfileType
|
||
d.AnchorRoundStatus = data.AnchorRoundStatus
|
||
d.AnchorRecordStatus = data.AnchorRecordStatus
|
||
d.AnchorLevel = data.AnchorLevel
|
||
} else {
|
||
resp[data.RoomId] = data
|
||
}
|
||
}
|
||
return
|
||
}
|
||
|
||
func (d *Dao) dbFetchRoomInfo(ctx context.Context, roomIDs []int64, resp map[int64]*v1pb.RoomData, overwrite bool) (err error) {
|
||
if len(roomIDs) <= 0 {
|
||
return
|
||
}
|
||
|
||
valueList := ""
|
||
for i, id := range roomIDs {
|
||
if i > 0 {
|
||
valueList += ","
|
||
}
|
||
valueList += fmt.Sprintf("%d", id)
|
||
}
|
||
|
||
sql := fmt.Sprintf(_queryRoomInfo, valueList)
|
||
rows, err := d.db.Query(ctx, sql)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomInfo] get room record error(%v), roomIDs(%v)", err, roomIDs)
|
||
return err
|
||
}
|
||
|
||
defer rows.Close()
|
||
|
||
for rows.Next() {
|
||
data := &v1pb.RoomData{}
|
||
err = rows.Scan(&data.RoomId, &data.Uid, &data.Title, &data.Description, &data.Tags, &data.Background, &data.Cover, &data.LockStatus, &data.LockTime, &data.HiddenTime, &data.AnchorRecordSwitch, &data.AnchorRoundSwitch, &data.LiveStartTime, &data.LiveScreenType, &data.AreaId, &data.ParentAreaId, &data.LiveType)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomInfo] scan room record error(%v), roomIDs(%v)", err, roomIDs)
|
||
return err
|
||
}
|
||
if overwrite {
|
||
d := resp[data.RoomId]
|
||
d.Uid = data.Uid
|
||
d.Title = data.Title
|
||
d.Description = data.Description
|
||
d.Tags = data.Tags
|
||
d.Background = data.Background
|
||
d.Cover = data.Cover
|
||
d.LockStatus = data.LockStatus
|
||
d.LockTime = data.LockTime
|
||
d.HiddenTime = data.HiddenTime
|
||
d.AnchorRecordSwitch = data.AnchorRecordSwitch
|
||
d.AnchorRoundSwitch = data.AnchorRoundSwitch
|
||
d.LiveStartTime = data.LiveStartTime
|
||
d.LiveScreenType = data.LiveScreenType
|
||
d.AreaId = data.AreaId
|
||
d.ParentAreaId = data.ParentAreaId
|
||
d.LiveType = data.LiveType
|
||
} else {
|
||
resp[data.RoomId] = data
|
||
}
|
||
|
||
d.dbDealWithStatus(ctx, resp[data.RoomId])
|
||
}
|
||
return
|
||
}
|
||
|
||
func (d *Dao) dbFetchTagInfo(ctx context.Context, roomIDs []int64, resp map[int64]*v1pb.RoomData) (err error) {
|
||
if len(roomIDs) <= 0 {
|
||
return
|
||
}
|
||
|
||
valueList := ""
|
||
for i, id := range roomIDs {
|
||
if i > 0 {
|
||
valueList += ","
|
||
}
|
||
valueList += fmt.Sprintf("%d", id)
|
||
}
|
||
|
||
sql := fmt.Sprintf(_queryTagInfo, _tagTable, valueList)
|
||
rows, err := d.db.Query(ctx, sql, time.Now().Unix())
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchTagInfo] get room record error(%v), roomIDs(%v)", err, roomIDs)
|
||
return err
|
||
}
|
||
|
||
defer rows.Close()
|
||
|
||
for rows.Next() {
|
||
var roomID int64
|
||
data := &v1pb.TagData{}
|
||
err = rows.Scan(&roomID, &data.TagId, &data.TagSubId, &data.TagValue, &data.TagExt, &data.TagExpireAt)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchTagInfo] scan room record error(%v), roomIDs(%v)", err, roomIDs)
|
||
return err
|
||
}
|
||
|
||
if resp[roomID] == nil {
|
||
resp[roomID] = &v1pb.RoomData{}
|
||
}
|
||
|
||
if resp[roomID].TagList == nil {
|
||
resp[roomID].TagList = make([]*v1pb.TagData, 0)
|
||
}
|
||
|
||
resp[roomID].TagList = append(resp[roomID].TagList, data)
|
||
}
|
||
return
|
||
}
|
||
|
||
func (d *Dao) dbFetchExtInfo(ctx context.Context, roomIDs []int64, resp map[int64]*v1pb.RoomData) (err error) {
|
||
if len(roomIDs) <= 0 {
|
||
return
|
||
}
|
||
|
||
sharding := make(map[int64][]int64)
|
||
for i := 0; i < 10; i++ {
|
||
sharding[int64(i)] = make([]int64, 0, len(roomIDs))
|
||
}
|
||
for _, id := range roomIDs {
|
||
sharding[id%ROOM_EXT_SHARDING] = append(sharding[id%ROOM_EXT_SHARDING], id)
|
||
}
|
||
|
||
for shard, ids := range sharding {
|
||
if len(ids) <= 0 {
|
||
continue
|
||
}
|
||
|
||
valueList := ""
|
||
for i, id := range ids {
|
||
if i > 0 {
|
||
valueList += ","
|
||
}
|
||
valueList += fmt.Sprintf("%d", id)
|
||
}
|
||
|
||
sql := fmt.Sprintf(_queryRoomExtInfo, _roomExtTablePrefix, shard, valueList)
|
||
rows, err := d.db.Query(ctx, sql)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchExtInfo] get room ext record error(%v), roomIDs(%v)", err, ids)
|
||
return err
|
||
}
|
||
|
||
defer rows.Close()
|
||
|
||
for rows.Next() {
|
||
var roomID int64
|
||
var keyframe string
|
||
var popularityCount int64
|
||
err = rows.Scan(&roomID, &keyframe, &popularityCount)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchExtInfo] scan room ext record error(%v), roomIDs(%v)", err, ids)
|
||
return err
|
||
}
|
||
|
||
resp[roomID].Keyframe = keyframe
|
||
resp[roomID].PopularityCount = popularityCount
|
||
}
|
||
}
|
||
return
|
||
}
|
||
|
||
// dbFetchRoomByIDs implementation
|
||
// dbFetchRoomByIDs 查询房间信息
|
||
func (d *Dao) dbFetchRoomByIDs(ctx context.Context, req *v1pb.RoomByIDsReq) (resp *v1pb.RoomByIDsResp, err error) {
|
||
resp = &v1pb.RoomByIDsResp{
|
||
RoomDataSet: make(map[int64]*v1pb.RoomData),
|
||
}
|
||
|
||
roomIDs := make([]int64, 0, len(req.Uids))
|
||
if len(req.RoomIds) > 0 {
|
||
for _, id := range req.RoomIds {
|
||
roomIDs = append(roomIDs, id)
|
||
}
|
||
|
||
// 先查room表
|
||
err = d.dbFetchRoomInfo(ctx, roomIDs, resp.RoomDataSet, false)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomByIDs] get room record error(%v), req(%v)", err, req)
|
||
return nil, err
|
||
}
|
||
|
||
uids := make([]int64, 0, len(req.RoomIds))
|
||
for _, v := range resp.RoomDataSet {
|
||
uids = append(uids, v.Uid)
|
||
}
|
||
|
||
err = d.dbFetchAnchorInfo(ctx, uids, resp.RoomDataSet, true)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomByIDs] get anchor record error(%v), req(%v)", err, req)
|
||
return nil, err
|
||
}
|
||
} else if len(req.Uids) > 0 {
|
||
// 先查anchor表
|
||
uids := make([]int64, 0, len(req.Uids))
|
||
for _, id := range req.Uids {
|
||
uids = append(uids, id)
|
||
}
|
||
|
||
err = d.dbFetchAnchorInfo(ctx, uids, resp.RoomDataSet, false)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomByIDs] get anchor record error(%v), req(%v)", err, req)
|
||
return nil, err
|
||
}
|
||
|
||
for _, v := range resp.RoomDataSet {
|
||
roomIDs = append(roomIDs, v.RoomId)
|
||
}
|
||
|
||
err = d.dbFetchRoomInfo(ctx, roomIDs, resp.RoomDataSet, true)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomByIDs] get room record error(%v), req(%v)", err, req)
|
||
return nil, err
|
||
}
|
||
}
|
||
|
||
// Ext Info
|
||
err = d.dbFetchExtInfo(ctx, roomIDs, resp.RoomDataSet)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomByIDs] get room ext record error(%v), req(%v)", err, req)
|
||
return nil, err
|
||
}
|
||
|
||
// Tag List
|
||
err = d.dbFetchTagInfo(ctx, roomIDs, resp.RoomDataSet)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbFetchRoomByIDs] get tag record error(%v), req(%v)", err, req)
|
||
return nil, err
|
||
}
|
||
|
||
// TODO: @wangyao需要处理short_id
|
||
return
|
||
}
|
||
|
||
// dbOnlineListByArea implementation
|
||
// dbOnlineListByArea 分区在线房间列表
|
||
func (d *Dao) dbOnlineListByArea(ctx context.Context, areaId int64) (roomIDs []int64, err error) {
|
||
cond := ""
|
||
if areaId > 0 {
|
||
cond = fmt.Sprintf(_queryOnlineRoomByAreaCond, areaId, areaId)
|
||
}
|
||
|
||
sql := fmt.Sprintf(_queryOnlineRoomByAreaInfo, cond)
|
||
rows, err := d.db.Query(ctx, sql)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbOnlineListByArea] get online room list by area error(%v), areaId(%v)", err, areaId)
|
||
return nil, err
|
||
}
|
||
|
||
defer rows.Close()
|
||
|
||
roomIDs = make([]int64, 0)
|
||
|
||
for rows.Next() {
|
||
var roomid int64
|
||
err = rows.Scan(&roomid)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|dbOnlineListByArea] scan online room list by area error(%v), areaId(%v)", err, areaId)
|
||
return nil, err
|
||
}
|
||
roomIDs = append(roomIDs, roomid)
|
||
}
|
||
return
|
||
}
|
||
|
||
// roomCreate implementation
|
||
// roomCreate 房间创建
|
||
func (d *Dao) roomCreate(ctx context.Context, req *v1pb.RoomCreateReq) (resp *v1pb.RoomCreateResp, err error) {
|
||
resp = &v1pb.RoomCreateResp{}
|
||
|
||
tx, err := d.db.Begin(ctx)
|
||
if err != nil {
|
||
err = errors.WithStack(err)
|
||
return resp, err
|
||
}
|
||
|
||
if req.RoomId != 0 {
|
||
resp.RoomId = req.RoomId
|
||
sql := fmt.Sprintf(_addRoomInfo2, _roomTable)
|
||
_, err = tx.Exec(sql, req.Uid, req.RoomId)
|
||
if err != nil {
|
||
if e := tx.Rollback(); e != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomCreate] create room record rollback error(%v), req(%v)", e, req)
|
||
}
|
||
// unique key exists error
|
||
log.Error("[dao.dao-anchor.mysql|roomCreate] create room record error(%v), req(%v)", err, req)
|
||
return resp, err
|
||
}
|
||
} else {
|
||
sql := fmt.Sprintf(_addRoomInfo1, _roomTable)
|
||
res, err := tx.Exec(sql, req.Uid)
|
||
if err != nil {
|
||
if e := tx.Rollback(); e != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomCreate] create room record rollback error(%v), req(%v)", e, req)
|
||
}
|
||
// unique key exists error
|
||
log.Error("[dao.dao-anchor.mysql|roomCreate] create room record error(%v), req(%v)", err, req)
|
||
return resp, err
|
||
}
|
||
if resp.RoomId, err = res.LastInsertId(); err != nil {
|
||
err = errors.WithStack(err)
|
||
log.Error("[dao.dao-anchor.mysql|AddGuard] get last insert id error(%v), req(%v)", err, req)
|
||
}
|
||
}
|
||
|
||
sql := fmt.Sprintf(_addRoomExtInfo, _roomExtTablePrefix, resp.RoomId%ROOM_EXT_SHARDING)
|
||
if _, err = tx.Exec(sql, resp.RoomId); err != nil {
|
||
if e := tx.Rollback(); e != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomCreate] create room extend record rollback error(%v), req(%v)", e, req)
|
||
}
|
||
log.Error("[dao.dao-anchor.mysql|roomCreate] create room extend record error(%v), req(%v)", err, req)
|
||
return resp, err
|
||
}
|
||
|
||
sql = fmt.Sprintf(_addAnchorInfo, _anchorTable)
|
||
if _, err = tx.Exec(sql, req.Uid, resp.RoomId); err != nil {
|
||
if e := tx.Rollback(); e != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomCreate] create anchor record rollback error(%v), req(%v)", e, req)
|
||
}
|
||
log.Error("[dao.dao-anchor.mysql|roomCreate] create anchor record error(%v), req(%v)", err, req)
|
||
return resp, err
|
||
}
|
||
|
||
if err = tx.Commit(); err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomCreate] commit error(%v), req(%v)", err, req)
|
||
return resp, err
|
||
}
|
||
return
|
||
}
|
||
|
||
// roomUpdate implementation
|
||
// roomUpdate 房间信息更新
|
||
func (d *Dao) roomUpdate(ctx context.Context, req *v1pb.RoomUpdateReq) (resp *v1pb.UpdateResp, err error) {
|
||
updateSub := ""
|
||
args := make([]interface{}, len(req.Fields)+1)
|
||
args[len(req.Fields)] = req.RoomId
|
||
|
||
for i, f := range req.Fields {
|
||
switch f {
|
||
case "title":
|
||
args[i] = req.Title
|
||
case "cover":
|
||
args[i] = req.Cover
|
||
case "tags":
|
||
args[i] = req.Tags
|
||
case "background":
|
||
args[i] = req.Background
|
||
case "description":
|
||
args[i] = req.Description
|
||
case "live_start_time":
|
||
args[i] = req.LiveStartTime
|
||
if req.LiveStartTime > 0 {
|
||
if i > 0 {
|
||
updateSub += ","
|
||
}
|
||
updateSub += "`live_mark`=1"
|
||
if i == 0 {
|
||
updateSub += ","
|
||
}
|
||
}
|
||
case "live_screen_type":
|
||
args[i] = req.LiveScreenType
|
||
case "live_type":
|
||
args[i] = req.LiveType
|
||
case "lock_status":
|
||
args[i] = req.LockStatus
|
||
case "lock_time":
|
||
args[i] = req.LockTime
|
||
case "hidden_time":
|
||
args[i] = req.HiddenTime
|
||
case "area_id":
|
||
f = "live_area_id"
|
||
args[i] = req.AreaId
|
||
areaInfo := &model.AreaInfo{}
|
||
// 审核后台会设置成无分区
|
||
if req.AreaId > 0 {
|
||
areaInfo, err = d.dbFetchAreaInfo(ctx, req.AreaId)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomUpdate] fetch area info error(%v), req(%v), areaid(%v)", err, req, req.AreaId)
|
||
return
|
||
}
|
||
}
|
||
if i > 0 {
|
||
updateSub += ","
|
||
}
|
||
updateSub += fmt.Sprintf("`live_area_parent_id`=%d", areaInfo.ParentAreaID)
|
||
if i == 0 {
|
||
updateSub += ","
|
||
}
|
||
case "anchor_round_switch":
|
||
f = "round_switch"
|
||
args[i] = req.AnchorRoundSwitch
|
||
case "anchor_record_switch":
|
||
f = "record_switch"
|
||
args[i] = req.AnchorRecordSwitch
|
||
default:
|
||
log.Error("[dao.dao-anchor.mysql|roomUpdate] unsupported field(%v), req(%v)", f, req)
|
||
err = ecode.InvalidParam
|
||
return
|
||
}
|
||
if i > 0 {
|
||
updateSub += ","
|
||
}
|
||
updateSub += fmt.Sprintf("`%s`=?", f)
|
||
}
|
||
|
||
resp = &v1pb.UpdateResp{}
|
||
|
||
sql := fmt.Sprintf(_updateRoomInfo, _roomTable, updateSub)
|
||
res, err := d.db.Exec(ctx, sql, args...)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomUpdate] update room record error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
|
||
resp.AffectedRows, err = res.RowsAffected()
|
||
return
|
||
}
|
||
|
||
// roomExtendUpdate implementation
|
||
// roomExtendUpdate 房间扩展信息更新
|
||
func (d *Dao) roomExtendUpdate(ctx context.Context, req *v1pb.RoomExtendUpdateReq) (resp *v1pb.UpdateResp, err error) {
|
||
if len(req.Fields) <= 0 {
|
||
log.Error("[dao.dao-anchor.mysql|roomExtendUpdate] no fields, req(%v)", req)
|
||
err = ecode.InvalidParam
|
||
return
|
||
}
|
||
|
||
updateSub := ""
|
||
args := make([]interface{}, len(req.Fields)+1)
|
||
args[len(req.Fields)] = req.RoomId
|
||
|
||
for i, f := range req.Fields {
|
||
switch f {
|
||
case "keyframe":
|
||
args[i] = req.Keyframe
|
||
case "danmu_count":
|
||
args[i] = req.DanmuCount
|
||
case "popularity_count":
|
||
args[i] = req.PopularityCount
|
||
case "audience_count":
|
||
args[i] = req.AudienceCount
|
||
case "gift_count":
|
||
args[i] = req.GiftCount
|
||
case "gift_gold_amount":
|
||
args[i] = req.GiftGoldAmount
|
||
case "gift_gold_count":
|
||
args[i] = req.GiftGoldCount
|
||
default:
|
||
log.Error("[dao.dao-anchor.mysql|roomExtendUpdate] unsupported field(%v), req(%v)", f, req)
|
||
err = ecode.InvalidParam
|
||
return
|
||
}
|
||
if i > 0 {
|
||
updateSub += ","
|
||
}
|
||
updateSub += fmt.Sprintf("`%s`=?", f)
|
||
}
|
||
|
||
resp = &v1pb.UpdateResp{}
|
||
|
||
sql := fmt.Sprintf(_updateRoomExtInfo, _roomExtTablePrefix, req.RoomId%10, updateSub)
|
||
res, err := d.db.Exec(ctx, sql, args...)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomExtendUpdate] update room extend record error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
|
||
resp.AffectedRows, err = res.RowsAffected()
|
||
return
|
||
}
|
||
|
||
// roomExtendIncre implementation
|
||
// roomExtendIncre 房间扩展信息增量更新
|
||
func (d *Dao) roomExtendIncre(ctx context.Context, req *v1pb.RoomExtendIncreReq) (resp *v1pb.UpdateResp, err error) {
|
||
if len(req.Fields) <= 0 {
|
||
log.Error("[dao.dao-anchor.mysql|roomExtendIncre] no fields, req(%v)", req)
|
||
err = ecode.InvalidParam
|
||
return
|
||
}
|
||
|
||
// TODO: req_id
|
||
updateSub := ""
|
||
args := make([]interface{}, len(req.Fields)+1)
|
||
args[len(req.Fields)] = req.RoomId
|
||
|
||
for i, f := range req.Fields {
|
||
switch f {
|
||
case "danmu_count":
|
||
args[i] = req.DanmuCount
|
||
case "popularity_count":
|
||
args[i] = req.PopularityCount
|
||
case "audience_count":
|
||
args[i] = req.AudienceCount
|
||
case "gift_count":
|
||
args[i] = req.GiftCount
|
||
case "gift_gold_amount":
|
||
args[i] = req.GiftGoldAmount
|
||
case "gift_gold_count":
|
||
args[i] = req.GiftGoldCount
|
||
default:
|
||
log.Error("[dao.dao-anchor.mysql|roomExtendIncre] unsupported field(%v), req(%v)", f, req)
|
||
err = ecode.InvalidParam
|
||
return
|
||
}
|
||
if i > 0 {
|
||
updateSub += ","
|
||
}
|
||
updateSub += fmt.Sprintf("`%s`=`%s`+(?)", f, f)
|
||
}
|
||
|
||
resp = &v1pb.UpdateResp{}
|
||
|
||
sql := fmt.Sprintf(_updateRoomExtInfo, _roomExtTablePrefix, req.RoomId%10, updateSub)
|
||
res, err := d.db.Exec(ctx, sql, args...)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomExtendIncre] update room extend increment record error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
|
||
resp.AffectedRows, err = res.RowsAffected()
|
||
return
|
||
}
|
||
|
||
// roomTagCreate implementation
|
||
// roomTagCreate 房间Tag创建
|
||
func (d *Dao) roomTagCreate(ctx context.Context, req *v1pb.RoomTagCreateReq) (resp *v1pb.UpdateResp, err error) {
|
||
resp = &v1pb.UpdateResp{}
|
||
|
||
sql := fmt.Sprintf(_tagCreateInfo, _tagTable)
|
||
_, err = d.db.Exec(ctx, sql, req.RoomId, req.TagId, req.TagSubId, req.TagValue, req.TagExt, req.TagExpireAt, req.TagValue, req.TagExt, req.TagExpireAt)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomTagCreate] create room tag error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
|
||
resp.AffectedRows = 1
|
||
return
|
||
}
|
||
|
||
// roomAttrCreate implementation
|
||
// roomAttrCreate 房间Attr创建
|
||
func (d *Dao) roomAttrCreate(ctx context.Context, req *v1pb.RoomAttrCreateReq) (resp *v1pb.UpdateResp, err error) {
|
||
resp = &v1pb.UpdateResp{}
|
||
|
||
sql := fmt.Sprintf(_attrCreateInfo, _attrTable)
|
||
_, err = d.db.Exec(ctx, sql, req.RoomId, req.AttrId, req.AttrSubId, req.AttrValue, req.AttrExt, req.AttrValue, req.AttrExt)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomAttrCreate] create room attr error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
|
||
resp.AffectedRows = 1
|
||
return
|
||
}
|
||
|
||
// roomAttrSetEx implementation
|
||
// roomAttrSetEx 房间Attr更新/插入
|
||
func (d *Dao) roomAttrSetEx(ctx context.Context, req *v1pb.RoomAttrSetExReq) (resp *v1pb.UpdateResp, err error) {
|
||
needSet, err := RoomAttrNeedSet(d, ctx, req)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomAttrSetEx] set room attr error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
if needSet <= 0 {
|
||
return
|
||
}
|
||
if needSet == NEED_INSERT {
|
||
reqCreate := &v1pb.RoomAttrCreateReq{}
|
||
reqCreate.RoomId = req.RoomId
|
||
reqCreate.AttrId = req.AttrId
|
||
reqCreate.AttrSubId = req.AttrSubId
|
||
reqCreate.AttrValue = req.AttrValue
|
||
reqCreate.AttrExt = req.AttrExt
|
||
resp, err = d.roomAttrCreate(ctx, reqCreate)
|
||
} else {
|
||
if req.AttrId == ATTRID_RANK_LIST {
|
||
resp, err = d.roomAttrSetRoomId(ctx, req)
|
||
} else {
|
||
resp, err = d.roomAttrSetValue(ctx, req)
|
||
}
|
||
}
|
||
return
|
||
}
|
||
|
||
const (
|
||
NEED_INSERT = 1
|
||
NEED_UPDATE = 2
|
||
)
|
||
|
||
// roomAttrNeedSet 内部函数 0 不需要set 1 需要insert 2 需要update
|
||
func RoomAttrNeedSet(d *Dao, ctx context.Context, req *v1pb.RoomAttrSetExReq) (resp int, err error) {
|
||
attrId := req.AttrId
|
||
//排行榜设计:更新roomID
|
||
resp = 0
|
||
if attrId == ATTRID_RANK_LIST {
|
||
roomID := 0
|
||
sql := fmt.Sprintf(_attrSelectRoomId, _attrTable)
|
||
err = d.db.QueryRow(ctx, sql, req.AttrId, req.AttrSubId, req.AttrValue).Scan(&roomID)
|
||
if err != nil && err.Error() == "sql: no rows in result set" {
|
||
err = nil
|
||
resp = NEED_INSERT
|
||
return
|
||
}
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|RoomAttrNeedSet] set room attr_rank error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
if int64(roomID) != req.RoomId {
|
||
resp = NEED_UPDATE
|
||
}
|
||
} else {
|
||
value := 0
|
||
sql := fmt.Sprintf(_attrSelectValue, _attrTable)
|
||
err = d.db.QueryRow(ctx, sql, req.AttrId, req.AttrSubId, req.AttrValue).Scan(value)
|
||
if err != nil && err.Error() == "sql: no rows in result set" {
|
||
err = nil
|
||
resp = NEED_INSERT
|
||
return
|
||
}
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|RoomAttrNeedSet] set room attr error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
if int64(value) != req.AttrValue {
|
||
resp = NEED_UPDATE
|
||
}
|
||
}
|
||
|
||
return
|
||
}
|
||
|
||
//roomAttrSet 更新value
|
||
func (d *Dao) roomAttrSetValue(ctx context.Context, req *v1pb.RoomAttrSetExReq) (resp *v1pb.UpdateResp, err error) {
|
||
resp = &v1pb.UpdateResp{}
|
||
sql := fmt.Sprintf(_attrSetValue, _attrTable)
|
||
res, err := d.db.Exec(ctx, sql, req.AttrValue, req.RoomId, req.AttrId, req.AttrSubId)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomAttrSetEx] set room attr error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
resp.AffectedRows, err = res.RowsAffected()
|
||
return
|
||
}
|
||
|
||
//roomAttrSetRoomId 更新roomID
|
||
func (d *Dao) roomAttrSetRoomId(ctx context.Context, req *v1pb.RoomAttrSetExReq) (resp *v1pb.UpdateResp, err error) {
|
||
resp = &v1pb.UpdateResp{}
|
||
sql := fmt.Sprintf(_attrSetRoomId, _attrTable)
|
||
res, err := d.db.Exec(ctx, sql, req.RoomId, req.AttrId, req.AttrSubId, req.AttrValue)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomAttrSetEx] set room attr error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
resp.AffectedRows, err = res.RowsAffected()
|
||
return
|
||
}
|
||
|
||
// anchorUpdate implementation
|
||
// anchorUpdate 主播信息更新
|
||
func (d *Dao) anchorUpdate(ctx context.Context, req *v1pb.AnchorUpdateReq) (resp *v1pb.UpdateResp, err error) {
|
||
updateSub := ""
|
||
args := make([]interface{}, len(req.Fields)+1)
|
||
args[len(req.Fields)] = req.Uid
|
||
|
||
for i, f := range req.Fields {
|
||
switch f {
|
||
case "profile_type":
|
||
args[i] = req.ProfileType
|
||
case "san_score":
|
||
args[i] = req.SanScore
|
||
case "round_status":
|
||
args[i] = req.RoundStatus
|
||
case "record_status":
|
||
args[i] = req.RecordStatus
|
||
case "exp":
|
||
args[i] = req.Exp
|
||
default:
|
||
log.Error("[dao.dao-anchor.mysql|anchorUpdate] unsupported field(%v), req(%v)", f, req)
|
||
err = ecode.InvalidParam
|
||
return
|
||
}
|
||
if i > 0 {
|
||
updateSub += ","
|
||
}
|
||
updateSub += fmt.Sprintf("`%s`=?", f)
|
||
}
|
||
|
||
resp = &v1pb.UpdateResp{}
|
||
|
||
sql := fmt.Sprintf(_updateAnchorInfo, _anchorTable, updateSub)
|
||
res, err := d.db.Exec(ctx, sql, args...)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|anchorUpdate] update anchor record error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
resp.AffectedRows, err = res.RowsAffected()
|
||
return
|
||
}
|
||
|
||
// anchorIncre implementation
|
||
// anchorIncre 主播信息增量更新
|
||
func (d *Dao) anchorIncre(ctx context.Context, req *v1pb.AnchorIncreReq) (resp *v1pb.UpdateResp, err error) {
|
||
// TODO: req_id
|
||
updateSub := ""
|
||
args := make([]interface{}, len(req.Fields)+1)
|
||
args[len(req.Fields)] = req.Uid
|
||
|
||
for i, f := range req.Fields {
|
||
switch f {
|
||
case "san_score":
|
||
args[i] = req.SanScore
|
||
case "exp":
|
||
args[i] = req.Exp
|
||
default:
|
||
log.Error("[dao.dao-anchor.mysql|anchorIncre] unsupported field(%v), req(%v)", f, req)
|
||
err = ecode.InvalidParam
|
||
return
|
||
}
|
||
if i > 0 {
|
||
updateSub += ","
|
||
}
|
||
updateSub += fmt.Sprintf("`%s`=`%s`+(?)", f, f)
|
||
}
|
||
|
||
resp = &v1pb.UpdateResp{}
|
||
|
||
sql := fmt.Sprintf(_updateAnchorInfo, _anchorTable, updateSub)
|
||
res, err := d.db.Exec(ctx, sql, args...)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|anchorUpdate] update anchor increment record error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
resp.AffectedRows, err = res.RowsAffected()
|
||
return
|
||
}
|
||
|
||
// fetchAreas implementation
|
||
// fetchAreas 根据父分区号查询子分区
|
||
// If the request area-id does not exist, the function returns with the `err` being set.
|
||
func (d *Dao) fetchAreas(ctx context.Context, req *v1pb.FetchAreasReq) (resp *v1pb.FetchAreasResp, err error) {
|
||
// Query parent area info first and fail fast in case the area doesn't exist.
|
||
areaInfo, err := d.dbFetchAreaInfo(ctx, req.AreaId)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|fetchAreas] fetch main area info error(%v), req area(%d)", err, req.AreaId)
|
||
return nil, err
|
||
}
|
||
|
||
resp = &v1pb.FetchAreasResp{
|
||
Info: &v1pb.AreaInfo{
|
||
AreaId: req.AreaId,
|
||
AreaName: areaInfo.AreaName,
|
||
},
|
||
}
|
||
|
||
sql := fmt.Sprintf(_querySubAreaInfo, _subAreaTable)
|
||
rows, err := d.dbLiveApp.Query(ctx, sql, req.AreaId)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|fetchAreas] fetch area records error(%v), req area(%d)", err, req.AreaId)
|
||
return nil, err
|
||
}
|
||
|
||
defer rows.Close()
|
||
|
||
for rows.Next() {
|
||
var subAreaID int64
|
||
var subAreaName string
|
||
if err = rows.Scan(&subAreaID, &subAreaName); err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|fetchAreas] fetch subarea info error(%v), req area(%d)", err, req.AreaId)
|
||
return nil, err
|
||
}
|
||
resp.Areas = append(resp.Areas, &v1pb.AreaInfo{
|
||
AreaId: subAreaID,
|
||
AreaName: subAreaName,
|
||
})
|
||
}
|
||
|
||
return
|
||
}
|
||
|
||
// fetchAttrByIDs implementation
|
||
// fetchAttrByIDs 批量根据房间号查询指标
|
||
func (d *Dao) fetchAttrByIDs(ctx context.Context, req *v1pb.FetchAttrByIDsReq) (resp *v1pb.FetchAttrByIDsResp, err error) {
|
||
if len(req.RoomIds) <= 0 {
|
||
return
|
||
}
|
||
|
||
resp = &v1pb.FetchAttrByIDsResp{
|
||
Attrs: make(map[int64]*v1pb.AttrData),
|
||
}
|
||
|
||
valueList := ""
|
||
for i, id := range req.RoomIds {
|
||
if i > 0 {
|
||
valueList += ","
|
||
}
|
||
valueList += fmt.Sprintf("%d", id)
|
||
}
|
||
|
||
sql := fmt.Sprintf(_queryAttrInfo, _attrTable, valueList)
|
||
rows, err := d.db.Query(ctx, sql, req.AttrId, req.AttrSubId)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|fetchAttrByIDs] get attr record error(%v), req(%v)", err, req)
|
||
return nil, err
|
||
}
|
||
|
||
defer rows.Close()
|
||
|
||
for rows.Next() {
|
||
data := &v1pb.AttrData{
|
||
AttrId: req.AttrId,
|
||
AttrSubId: req.AttrSubId,
|
||
}
|
||
err = rows.Scan(&data.RoomId, &data.AttrValue)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|fetchAttrByIDs] scan attr record error(%v), req(%v)", err, req)
|
||
return nil, err
|
||
}
|
||
resp.Attrs[data.RoomId] = data
|
||
}
|
||
return
|
||
}
|
||
|
||
// deleteAttr implementation
|
||
// deleteAttr 删除一个指标
|
||
func (d *Dao) deleteAttr(ctx context.Context, req *v1pb.DeleteAttrReq) (resp *v1pb.UpdateResp, err error) {
|
||
sql := fmt.Sprintf(_deleteAttrInfo, _attrTable)
|
||
res, err := d.db.Exec(ctx, sql, req.AttrId, req.AttrSubId)
|
||
if err != nil {
|
||
log.Error("[dao.dao-anchor.mysql|roomExtendIncre] update room extend increment record error(%v), req(%v)", err, req)
|
||
return
|
||
}
|
||
|
||
resp = &v1pb.UpdateResp{}
|
||
resp.AffectedRows, err = res.RowsAffected()
|
||
return
|
||
}
|