...
 
Commits (146)
package groupPower_k
import (
"fmt"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key"
)
// 家族之星榜单
// type: 1:送礼 2:活跃 3:收礼
// date:天/周/月的开始时间
const GroupPowerStarPrefix = "groupPowerStar:${type}:${period}:${groupPowerId}:${date}" // zset member:userId score:分数
func GetGroupPowerStarRankKey(_type groupPower_e.GroupPowerStarType, period string, groupPowerId uint64, date string) string {
return redis_key.ReplaceKey(GroupPowerStarPrefix,
fmt.Sprintf("%d", _type), period, fmt.Sprintf("%d", groupPowerId), date)
}
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
const ( const (
UserEnterRoomPrefix = "uer:" UserEnterRoomPrefix = "uer:"
UserEnterRoomUserKey = UserEnterRoomPrefix + "u:${user_id}" UserEnterRoomUserKey = UserEnterRoomPrefix + "u:${user_id}"
UserEnterRoomGroupKey = UserEnterRoomPrefix + "g:${user_id}" UserEnterRoomGroupKey = UserEnterRoomPrefix + "g:${group_id}"
) )
func GetUserEnterRoomUserKey(userId uint64) string { func GetUserEnterRoomUserKey(userId uint64) string {
......
...@@ -10,9 +10,33 @@ import ( ...@@ -10,9 +10,33 @@ import (
const ( const (
MicPrefix = "mic:" MicPrefix = "mic:"
MicDayInvite = MicPrefix + "day:invite:${userId}:${date}" // string 自动被邀请上麦,1天一次,TTL:24H MicDayInvite = MicPrefix + "day:invite:${userId}:${date}" // string 自动被邀请上麦,1天一次,TTL:24H
MicGroupPowerOnMic = MicPrefix + "groupPower:${userId}:${date}" // 家族内群上麦分钟数
MicUserOnMic = MicPrefix + "user:onMic:${tz}:${userId}:${date}"
MicGroupOnMic = MicPrefix + "group:onMic:${groupId}" // 在群组麦位上的人 hset field:micIndex member:userId
) )
func GetUserMicDayInvite(userId mysql.ID) string { func GetUserMicDayInvite(userId mysql.ID) string {
date := time.Now().Format("2006-01-02") date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicDayInvite, fmt.Sprintf("%d", userId), date) return redis_key.ReplaceKey(MicDayInvite, fmt.Sprintf("%d", userId), date)
} }
// 家族内群上麦分钟数
func GetMicGroupPowerOnMic(userId uint64) string {
date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicGroupPowerOnMic, fmt.Sprintf("%d", userId), date)
}
// 获取用户上麦时间
// 北京、沙特时间
func GetUserOnMicKey(userId uint64, tz, date string) string {
return redis_key.ReplaceKey(MicUserOnMic, tz, fmt.Sprintf("%d", userId), date)
}
// 获取群组麦位上的人
// 可能会有数据不一致,已原来麦位的key为准
// 这里用户快速获取群上麦位的人用,代替大量mget命令慢查询
func GetGroupOnMicUser(groupId string) string {
return redis_key.ReplaceKey(MicGroupOnMic, groupId)
}
package mic_k
// onMic异步入库
const (
OnMicQueue = "onMic:hilo_group"
)
func GetOnMicQueue() string {
return OnMicQueue
}
...@@ -249,6 +249,9 @@ const groupInUserDuration = "group_in_user_duration_{groupUuid}" ...@@ -249,6 +249,9 @@ const groupInUserDuration = "group_in_user_duration_{groupUuid}"
// 15天内进入房间的人数 // 15天内进入房间的人数
const roomVisitCount = "room_visit_count" const roomVisitCount = "room_visit_count"
// 15天内进入房间的人数 member groupId score 麦位有人的数量
const roomVisitCountZSet = "room_visit_count_zset"
// 用户进入过的房间及时间 // 用户进入过的房间及时间
const userEnterRoom = "enter_room_{userId}" const userEnterRoom = "enter_room_{userId}"
...@@ -757,18 +760,27 @@ func GetPrefixGroupMicNumType(groupUuid string) string { ...@@ -757,18 +760,27 @@ func GetPrefixGroupMicNumType(groupUuid string) string {
return strings.Replace(groupMicNumType, "{groupUuid}", groupUuid, -1) return strings.Replace(groupMicNumType, "{groupUuid}", groupUuid, -1)
} }
// Deprecated: 用户进房时间
// 用 uer:g:${group_id}代替
func GetPrefixGroupInUserDuration(groupUuid string) string { func GetPrefixGroupInUserDuration(groupUuid string) string {
return strings.Replace(groupInUserDuration, "{groupUuid}", groupUuid, -1) return strings.Replace(groupInUserDuration, "{groupUuid}", groupUuid, -1)
} }
// Deprecated: 用户进房时间
// 可用 uer:u:${user_id}代替
func GetUserEnterRoomKey(userId uint64) string { func GetUserEnterRoomKey(userId uint64) string {
return strings.Replace(userEnterRoom, "{userId}", strconv.FormatUint(userId, 10), -1) return strings.Replace(userEnterRoom, "{userId}", strconv.FormatUint(userId, 10), -1)
} }
// Deprecated: 用redis集群中的zset代替
func GetPrefixRoomVisitCount() string { func GetPrefixRoomVisitCount() string {
return roomVisitCount return roomVisitCount
} }
func GetPrefixRoomVisitCountZset() string {
return roomVisitCountZSet
}
func GetPrefixSupportLevel(date string) string { func GetPrefixSupportLevel(date string) string {
return strings.Replace(supportLevel, "{date}", date, -1) return strings.Replace(supportLevel, "{date}", date, -1)
} }
......
...@@ -5,15 +5,24 @@ import ( ...@@ -5,15 +5,24 @@ import (
"hilo-group/cron/gift_cron" "hilo-group/cron/gift_cron"
"hilo-group/cron/group_cron" "hilo-group/cron/group_cron"
"hilo-group/cron/mic_cron" "hilo-group/cron/mic_cron"
"hilo-group/cron/user_cron"
) )
func Init() { func Init() {
user_cron.LoadSvipVipNoble() // 加载用户特权
if !config.IsMaster() { if !config.IsMaster() {
return return
} }
gift_cron.SendGiftEventInit() // 礼物消息 //gift_cron.SendGiftEventInit() // 礼物消息
gift_cron.GiftRemark() // 礼物消息补偿 //gift_cron.GiftRemark() // 礼物消息补偿
gift_cron.SendGiftEvent() // 礼物事件
mic_cron.OnMicCheck() // 检查上麦 mic_cron.OnMicCheck() // 检查上麦
mic_cron.OnMicQueue() // 检查上麦-队列操作
group_cron.GroupPowerExpClear() // 清理家族经验/等级 group_cron.GroupPowerExpClear() // 清理家族经验/等级
group_cron.GroupPowerMonthRankAct() group_cron.GroupPowerMonthRankAct()
//group_cron.GroupInEventInit() // 进房事件
//group_cron.CreateGroup() //
group_cron.CalcGroupSupport() // 群组扶持计算
//group_cron.CalcGroupSupport_OldData()
group_cron.GroupCountryListSort()
} }
package gift_cron
import (
"context"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-group/_const/enum/gift_e"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/domain/cache/gift_c"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/event/gift_ev"
"hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m"
"time"
)
// 送礼事件
func SendGiftEvent() {
//if !config.IsMaster() {
// return
//}
go func() {
for true {
model := domain.CreateModelNil()
if sendGiftEvent := gift_c.BLPopQueueSendGift(model); sendGiftEvent != nil {
groupPowerGrade(model, sendGiftEvent) // 家族经验
groupPowerStar(model, sendGiftEvent) // 家族之星
groupSupportAddConsume(model, sendGiftEvent) // 群组扶持
}
}
}()
}
// 群组势力经验
func groupPowerGrade(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
model.Log.Infof("AddSendGiftEventAsync %+v", sendGiftEvent)
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return
}
exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId)
if err != nil {
model.Log.Infof("CheckGroupPowerUser fail %+v", err)
return
}
if exist {
exp := sendGiftEvent.GiftN * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) * sendGiftEvent.ResGift.DiamondNum
//return model.Transaction(func(model *domain.Model) error {
// return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
//})
//return groupPower_c.QueueGroupPowerGradeExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
if err := model.Transaction(func(model *domain.Model) error {
return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
}); err != nil {
model.Log.Errorf("IncrGroupPowerExp fail,data:%v-err:%v", *sendGiftEvent, err)
} else {
model.Log.Infof("IncrGroupPowerExp success,data:%v", *sendGiftEvent)
}
}
}
// 家族之星
func groupPowerStar(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return
}
var userIds = []mysql.ID{sendGiftEvent.SendUserId}
userIds = append(userIds, sendGiftEvent.ReceiveUserIds...)
groupPowers, err := groupPower_m.BatchGetGroupPowerUser(model, userIds)
if err != nil {
model.Log.Errorf("AddSendGiftEventAsync fail:%v", err)
return
}
// 送礼加分
if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds))
if err := groupPower_c.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId,
groupPower_e.GroupPowerStarTypeFamous, diamonds); err != nil {
model.Log.Errorf("IncrGroupPowerDayStarScore famous fail:%v", err)
}
}
// 收礼加分
for _, userId := range sendGiftEvent.ReceiveUserIds {
if data, ok := groupPowers[userId]; ok {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum
if err := groupPower_c.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId,
groupPower_e.GroupPowerStarTypeCharm, diamonds); err != nil {
model.Log.Errorf("IncrGroupPowerDayStarScore charm fail:%v", err)
}
}
}
return
}
// 群组扶持增加流水数据
func groupSupportAddConsume(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
if time.Now().Unix() <= 1693275900 {
return
}
model.Log.Infof("groupSupportAddConsume UserId:%d, sendGiftEvent:%+v", sendGiftEvent.SendUserId, sendGiftEvent)
if sendGiftEvent.SceneType != gift_e.GroupSceneType || sendGiftEvent.SceneUid == "" {
model.Log.Infof("groupSupportAddConsume UserId:%d, sendGiftEvent:%+v", sendGiftEvent.SendUserId, sendGiftEvent)
return
}
_, _, period := group_m.GetSupportLevelTime(time.Now())
// 钻石数
diamond := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds))
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
_, err := model.RedisCluster.ZIncrBy(context.Background(), keyDiamond, float64(diamond), sendGiftEvent.SceneUid).Result()
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, val:%d, member:%s, err:%v",
keyDiamond, diamond, sendGiftEvent.SceneUid, err)
}
err = redisCli.SetExpire(model.RedisCluster, keyDiamond, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, val:%d, member:%s, err:%v",
keyDiamond, diamond, sendGiftEvent.SceneUid, err)
}
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, sendGiftEvent.SceneUid)
err = model.RedisCluster.SAdd(context.Background(), keySupportNum, sendGiftEvent.SendUserId).Err()
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, UserId:%d, err:%v", keySupportNum, sendGiftEvent.SendUserId, err)
}
err = redisCli.SetExpire(model.RedisCluster, keySupportNum, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, UserId:%d, err:%v", keySupportNum, sendGiftEvent.SendUserId, err)
}
return
}
package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-group/_const/enum/group_e"
"hilo-group/domain/service/group_s"
)
func CreateGroup() {
if !config.IsMaster() {
return
}
c := cron.New()
spec := "0 15 15 16 8 ?"
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
userId := uint64(7687)
num := 20
if config.AppIsRelease() {
userId = 8350311
num = 1000
}
err := group_s.NewGroupService(model.MyContext).CreateGroupMulByUid(userId, num, group_e.TwoMicNumType)
if err != nil {
model.Log.Errorf("CreateGroupMulByUid fail:%v", err)
}
})
c.Start()
}
package group_cron
import (
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"hilo-group/domain/service/event_s"
"time"
)
// 进房事件
func GroupInEventInit() {
if !config.IsMaster() {
return
}
mylogrus.MyLog.Infof("GroupInEventInit")
go func() {
ticker := time.NewTicker(time.Millisecond * 500)
defer ticker.Stop()
for {
select {
case <-ticker.C:
//start := time.Now()
myCtx := mycontext.CreateMyContext(nil)
// 消费进房事件
if err := event_s.NewGroupInEventService(myCtx).Consume(); err != nil {
myCtx.Log.Errorf("groupInEvent consume fail:%v", err)
} else {
//myCtx.Log.Infof("groupInEvent consume success,cost:%v", time.Now().Sub(start))
}
}
}
}()
}
package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/domain/service/group_s"
)
// 清理家族经验和等级
func GroupCountryListSort() {
// 常用国家-每15分钟计算国家房间列表排序 /v1/imGroup/country [get] 接口
spec := "0 */15 * * * ?"
c := cron.New()
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
model.Log.Infof("GroupCountryListSort Common start")
group_s.SortGroupCommonCountryList(model)
model.Log.Infof("GroupCountryListSort Common end")
})
// 非常用国家-每60分钟计算国家房间列表排序 /v1/imGroup/country [get] 接口
spec2 := "0 59 * * * ?"
_ = c.AddFunc(spec2, func() {
var model = domain.CreateModelNil()
model.Log.Infof("GroupCountryListSort not Common start")
group_s.SortGroupNotCommonCountryList(model)
model.Log.Infof("GroupCountryListSort not Common end")
})
c.Start()
}
...@@ -2,12 +2,16 @@ package group_cron ...@@ -2,12 +2,16 @@ package group_cron
import ( import (
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron" "github.com/robfig/cron"
"hilo-group/domain/service/group_power_s" "hilo-group/domain/service/group_power_s"
) )
// 家族贡献月度排行榜发奖 // 家族贡献月度排行榜发奖
func GroupPowerMonthRankAct() { func GroupPowerMonthRankAct() {
if !config.IsMaster() {
return
}
c := cron.New() c := cron.New()
// 每月1号0:01结算发奖 // 每月1号0:01结算发奖
spec := "0 1 0 1 * ?" spec := "0 1 0 1 * ?"
......
package group_cron
import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/sdk/tencentyun"
"git.hilo.cn/hilo-common/utils"
"github.com/robfig/cron"
"hilo-group/_const/enum/gift_e"
"hilo-group/_const/enum/group_e"
"hilo-group/domain/model/gift_m"
"hilo-group/domain/model/group_m"
"hilo-group/domain/service/group_s"
"time"
)
// 群组扶持计算
func CalcGroupSupport() {
if !config.IsMaster() {
return
}
c := cron.New()
//北京时间周一0点,过了一秒后,
spec := "1 0 0 * * 1"
_ = c.AddFunc(spec, func() {
defer utils.CheckGoPanic()
var model = domain.CreateModelNil()
//开始
model.Log.Infof("cron CalcGroupSupport start")
calcTime := time.Now().AddDate(0, 0, -1)
if err := group_s.NewGroupService(model.MyContext).GroupSupportResult(calcTime); err != nil {
model.Log.Errorf("cron CalcGroupSupport faild calcTime:%v, err:%v", calcTime, err)
return
}
model.Log.Infof("cron CalcGroupSupport after GroupSupportResult")
//全服发送H5
if err := sendGroupSupportH5(domain.CreateModelContext(model.MyContext)); err != nil {
model.Log.Errorf("cron CalcGroupSupport err:%v", err)
} else {
model.Log.Infof("cron CalcGroupSupport success")
}
})
c.Start()
}
func sendGroupSupportH5(model *domain.Model) error {
groupIds, err := group_m.GetAllGroupsSorted(model)
if err != nil {
return err
}
model.Log.Infof("SendGroupSupportH5 groupIds:%v", groupIds)
groupSupportH5 := group_m.GroupSupportH5{
CommonPublicMsg: group_m.CommonPublicMsg{
Type: group_e.GroupSupportH5,
},
H5: config.GetH5Config().GROUP_SUPPORT,
}
buffer, err := json.Marshal(groupSupportH5)
if err != nil {
model.Log.Errorf("publicScreenMsg AddSendGiftAsync json.Marshal(giftContent) err:%v", err)
return err
}
content := string(buffer)
//策略1:for循环,没有开启协程,100个停一下
for i, _ := range groupIds {
func(groupId string, content string) {
defer utils.CheckGoPanic()
model.Log.Infof("SendGroupSupportH5 groupId:%v", groupId)
txGroupId, err := group_m.ToTxGroupId(model, groupId)
// 公屏消息
if err == nil {
tencentyun.SendCustomMsg(model.Log, txGroupId, nil, content, "")
}
}(groupIds[i], content)
if i != 0 && i%100 == 0 {
//躺平1秒
time.Sleep(1 * time.Second)
}
}
return nil
}
// 群组扶持计算-旧数据
func CalcGroupSupport_OldData() {
if !config.IsMaster() {
return
}
c := cron.New()
spec := "0 27 10 29 8 ?"
_ = c.AddFunc(spec, func() {
defer utils.CheckGoPanic()
var model = domain.CreateModelNil()
//开始
model.Log.Infof("CalcGroupSupport_OldData start")
//beginTime, endTime, period := group_m.GetSupportLevelTime(time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
beginTime, _, period := group_m.GetSupportLevelTime(time.Now())
endTime := time.Unix(1693275900, 0)
g := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, Model: model}
records, err := g.BatchGetConsumeByRange(beginTime, endTime)
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData beginTime:%v, endTime:%v, err:%v", beginTime, endTime, err)
return
}
// 流水写入redis
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
for _, r := range records {
if r.SceneUid == "" || r.Consume <= 0 {
continue
}
_, err = model.RedisCluster.ZIncrBy(context.Background(), keyDiamond, float64(r.Consume), r.SceneUid).Result()
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, val:%d, member:%s, err:%v",
keyDiamond, r.Consume, r.SceneUid, err)
}
}
err = redisCli.SetExpire(model.RedisCluster, keyDiamond, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, err:%v", keyDiamond, err)
return
}
// 支持者写入redis
for _, r := range records {
if r.SceneUid == "" || r.C <= 0 {
continue
}
// 支持者列表
support := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, SceneUid: r.SceneUid, Model: model}
uids, err := support.BatchGetSupportList(model, beginTime, endTime)
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData beginTime:%v, endTime:%v, imGroupId:%v, err:%v", beginTime, endTime, r.SceneUid, err)
continue
}
if len(uids) <= 0 {
continue
}
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, r.SceneUid)
for _, uid := range uids {
err = model.RedisCluster.SAdd(context.Background(), keySupportNum, uid).Err()
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, UserId:%d, err:%v", keySupportNum, uid, err)
}
}
err = redisCli.SetExpire(model.RedisCluster, keySupportNum, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("AddSendGiftEventAsync groupSupport key:%s, err:%v", keySupportNum, err)
}
}
model.Log.Infof("CalcGroupSupport_OldData end")
})
c.Start()
}
package mic_cron package mic_cron
import ( import (
"fmt"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron" "github.com/robfig/cron"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/cache/mic_c"
"hilo-group/domain/event/mic_ev" "hilo-group/domain/event/mic_ev"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/model/mic_m"
"hilo-group/domain/service/group_mic_s"
"time"
) )
func OnMicCheck() { func OnMicCheck() {
c := cron.New() c := cron.New()
//一分钟执行一次 //一分钟执行一次
spec := "0 */1 * * * ?" spec := "30 */1 * * * ?"
_ = c.AddFunc(spec, func() { _ = c.AddFunc(spec, func() {
//获取麦上的所有人 //获取麦上的所有人
var model = domain.CreateModelNil() var model = domain.CreateModelNil()
...@@ -20,14 +26,15 @@ func OnMicCheck() { ...@@ -20,14 +26,15 @@ func OnMicCheck() {
return return
} }
for _, groupId := range groupIds { for _, groupId := range groupIds {
onGroupMicKey := mic_k.GetGroupOnMicUser(groupId) // 同步在mic上的人
//遍历每个麦位 //遍历每个麦位
for i := 1; i <= 30; i++ { for i := 1; i <= group_m.MaxMicNum; i++ {
micUser, err := group_m.GetMicUser(model, groupId, i) micUser, err := group_m.GetMicUser(model, groupId, i)
if err != nil { if err != nil {
model.Log.Errorf("cron micIn group_m.GetMicUser err:%v", err) model.Log.Errorf("cron micIn group_m.GetMicUser err:%v", err)
} }
if micUser != nil { if micUser != nil {
if err := mic_ev.PublishOnMicEvent(model, &mic_ev.OnMicEvent{ if err := mic_c.QueueOnMic(model, &mic_ev.OnMicEvent{
GroupUuid: micUser.GroupUuid, GroupUuid: micUser.GroupUuid,
I: micUser.I, I: micUser.I,
ExternalId: micUser.ExternalId, ExternalId: micUser.ExternalId,
...@@ -35,11 +42,43 @@ func OnMicCheck() { ...@@ -35,11 +42,43 @@ func OnMicCheck() {
Forbid: micUser.Forbid, Forbid: micUser.Forbid,
Timestamp: micUser.Timestamp, Timestamp: micUser.Timestamp,
}); err != nil { }); err != nil {
model.Log.Errorf("PublishOnMicEvent fail:%v", err) model.Log.Errorf("QueueOnMic fail:%v", err)
} }
// 设置mic上的人
model.Redis.HSet(model, onGroupMicKey, i, micUser.UserId)
} else {
// 删除mic上的人
model.Redis.HDel(model, onGroupMicKey, fmt.Sprintf("%d", i))
} }
} }
} }
}) })
c.Start() c.Start()
} }
func OnMicQueue() {
for i := 0; i < 4; i++ {
go func() {
for true {
model := domain.CreateModelNil()
if onMic := mic_c.BLPopQueueOnMic(model); onMic != nil {
start := time.Now()
// 群组上麦经验
if err := group_mic_s.NewGroupPowerService(model.MyContext).IncrGroupPowerOnMicExpAndTime(onMic.GroupUuid, onMic.UserId, onMic.Timestamp); err != nil {
model.Log.Errorf("cron micIn GroupPowerOnMicExp err:%v", err)
} else {
model.Log.Infof("cron micIn GroupPowerOnMicExp success, groupId:%v, userId:%v,cost:%vs", onMic.GroupUuid, onMic.UserId, time.Now().Sub(start).Seconds())
}
// 用户上麦
//if err := mic_m.IncrUserOnMic(model, onMic.UserId, onMic.Timestamp); err != nil {
//if err := mic_m.IncrUserOnMicV2(model, onMic.UserId); err != nil {
if err := mic_m.IncrUserOnMicV3(model, onMic.UserId); err != nil {
model.Log.Errorf("cron micIn IncrUserOnMic err:%v", err)
} else {
}
}
}
}()
}
}
package user_cron
import (
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/domain/cache/user_c"
)
// 加载数据到lru
func LoadSvipVipNoble() {
go user_c.LoadAllSvipVipNoble(domain.CreateModelNil()) // 启动先执行一次
c := cron.New()
spec := "0 */30 * * * ?"
_ = c.AddFunc(spec, func() {
model := domain.CreateModelNil()
user_c.LoadAllSvipVipNoble(model)
})
c.Start()
}
...@@ -22,7 +22,15 @@ type BillboardUserInfo struct { ...@@ -22,7 +22,15 @@ type BillboardUserInfo struct {
Num uint64 `json:"num"` Num uint64 `json:"num"`
} }
func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ([]BillboardUserInfo, error) { //榜单中用户信息
type GroupTop3ConsumeUser struct {
//用户基本信息
UserBase user_cv.TopConsumersUser `json:"userBase"`
//数值
Num uint64 `json:"num"`
}
func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ([]GroupTop3ConsumeUser, error) {
now := time.Now() now := time.Now()
period := now.Format(utils.COMPACT_MONTH_FORMAT) period := now.Format(utils.COMPACT_MONTH_FORMAT)
data, err := getGroupTop3Consume(period, groupId) data, err := getGroupTop3Consume(period, groupId)
...@@ -59,7 +67,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ( ...@@ -59,7 +67,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) (
ret, err := saveGroupTop3Consume(period, groupId, diamonds) ret, err := saveGroupTop3Consume(period, groupId, diamonds)
model.Log.Infof("GetGroupTop3Consume SAVE ret = %d, err: %v", ret, err) model.Log.Infof("GetGroupTop3Consume SAVE ret = %d, err: %v", ret, err)
return result, nil
list := make([]GroupTop3ConsumeUser, 0, len(result))
for _, v := range result {
list = append(list, GroupTop3ConsumeUser{
UserBase: user_cv.TopConsumersUser{Id: v.UserBase.Id, Avatar: v.UserBase.Avatar, ExternalId: v.UserBase.ExternalId, Nick: v.UserBase.Nick},
})
}
return list, nil
} }
userIds := make([]uint64, 0) userIds := make([]uint64, 0)
...@@ -86,7 +102,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ( ...@@ -86,7 +102,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) (
}) })
} }
} }
return result, nil
list := make([]GroupTop3ConsumeUser, 0, len(result))
for _, v := range result {
list = append(list, GroupTop3ConsumeUser{
UserBase: user_cv.TopConsumersUser{Id: v.UserBase.Id, Avatar: v.UserBase.Avatar, ExternalId: v.UserBase.ExternalId, Nick: v.UserBase.Nick},
})
}
return list, nil
} }
func getGroupTop3Consume(period string, groupId string) (map[string]string, error) { func getGroupTop3Consume(period string, groupId string) (map[string]string, error) {
......
package diamond_cv package diamond_cv
import ( import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
. "git.hilo.cn/hilo-common/utils" . "git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"hilo-group/_const/enum/diamond_e"
"hilo-group/domain/model/bean_m"
"hilo-group/domain/model/diamond_m" "hilo-group/domain/model/diamond_m"
"hilo-group/myerr"
"strconv"
) )
type CvDiamond struct { type CvDiamond struct {
...@@ -26,33 +20,6 @@ type CvDiamondBean struct { ...@@ -26,33 +20,6 @@ type CvDiamondBean struct {
BeanNum string `json:"beanNum"` BeanNum string `json:"beanNum"`
} }
func GetDiamondBean(userId mysql.ID) (*CvDiamondBean, error) {
var diamondAccount diamond_m.DiamondAccount
err := mysql.Db.Where(&diamond_m.DiamondAccount{
UserId: userId,
}).First(&diamondAccount).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
diamondAccount = diamond_m.DiamondAccount{
DiamondNum: 0,
}
}
return nil, err
}
var beanAccount bean_m.BeanAccount
err = mysql.Db.Where(&bean_m.BeanAccount{
UserId: userId,
}).First(&beanAccount).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
beanAccount = bean_m.BeanAccount{
BeanNum: 0,
}
}
}
return &CvDiamondBean{DiamondNum: diamondAccount.DiamondNum, BeanNum: strconv.FormatFloat(float64(beanAccount.BeanNum)/100, 'f', 2, 64)}, nil
}
type CvDiamondDetail struct { type CvDiamondDetail struct {
//1:增加 2:减少 //1:增加 2:减少
...@@ -75,112 +42,3 @@ func GetDiamond(userId mysql.ID) (*CvDiamond, error) { ...@@ -75,112 +42,3 @@ func GetDiamond(userId mysql.ID) (*CvDiamond, error) {
} }
return &CvDiamond{DiamondNum: NumToUint32(&diamondAccount.DiamondNum), PinkDiamondNum: NumToUint32(&diamondAccount.PinkDiamondNum)}, nil return &CvDiamond{DiamondNum: NumToUint32(&diamondAccount.DiamondNum), PinkDiamondNum: NumToUint32(&diamondAccount.PinkDiamondNum)}, nil
} }
\ No newline at end of file
func GetDiamondBalances(userIds []mysql.ID) (map[mysql.ID]mysql.Num, error) {
result := make(map[mysql.ID]mysql.Num, len(userIds))
data := make([]diamond_m.DiamondAccount, 0)
err := mysql.Db.Where("user_id IN ?", userIds).Find(&data).Error
if err != nil {
return nil, err
}
for _, i := range data {
result[i.UserId] = i.DiamondNum
}
return result, nil
}
//充值记录
func GetDiamondBuyList(userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
var diamondAccountDetails []diamond_m.DiamondAccountDetail
if err := mysql.Db.Model(&diamond_m.DiamondAccountDetail{}).
Where("user_id = ? AND operate_type in (?)", userId, []uint8{diamond_e.BuyDiamond, diamond_e.DealerTransfer, diamond_e.Checkout, diamond_e.PayerMax, diamond_e.Paypal}).
Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
return nil, err
}
var cvDiamondDetails []*CvDiamondDetail
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
//钻石明细,不包括充值
func GetDiamondDetailList(model *domain.Model, userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
diamondAccountDetails := make([]*diamond_m.DiamondAccountDetail, 0)
offset := (pageIndex - 1) * pageSize
optList := []int{int(diamond_e.BuyDiamond), int(diamond_e.DealerTransfer), int(diamond_e.Checkout), int(diamond_e.PayerMax)}
details := make([]*diamond_m.DiamondAccountDetail, 0)
if offset == 0 { // 首页请求数据,获取 pageSize*3 条过滤返回
sql := "select * from diamond_account_detail where user_id = ? order by id desc limit ?"
if err := mysql.Db.WithContext(model).Raw(sql, userId, pageSize*3).Find(&details).Error; err != nil {
return nil, myerr.WrapErr(err)
}
notInMap := make(map[int]bool)
for _, v := range optList {
notInMap[v] = true
}
for _, v := range details {
if _, ok := notInMap[int(v.OperateType)]; !ok {
diamondAccountDetails = append(diamondAccountDetails, v)
}
}
if len(diamondAccountDetails) > pageSize {
diamondAccountDetails = diamondAccountDetails[:pageSize]
}
}
// 非首页,或者首页没取满 pageSize 条
if offset > 0 || (len(details) == pageSize*3 && len(diamondAccountDetails) < pageSize) {
diamondAccountDetails = make([]*diamond_m.DiamondAccountDetail, 0)
sql := "select * from diamond_account_detail where user_id = ? and operate_type not in (?) order by id desc limit ?,?"
if err := mysql.Db.WithContext(model).Raw(sql, userId, optList, offset, pageSize).
Find(&diamondAccountDetails).Error; err != nil {
return nil, myerr.WrapErr(err)
}
}
//if err := mysql.Db.Table("diamond_account_detail FORCE INDEX(Index_1)").
// Where("user_id = ? AND operate_type not in (?)", userId,
// []int{int(diamond_m2.BuyDiamond), int(diamond_m2.DealerTransfer), int(diamond_m2.Checkout), int(diamond_m2.PayerMax)}).
// Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
// return nil, myerr.WrapErr(err)
//}
cvDiamondDetails := []*CvDiamondDetail{}
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
//粉钻流水,包含充值
func GetPinkDiamondDetailList(userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
var diamondAccountDetails []diamond_m.DiamondPinkAccountDetail
if err := mysql.Db.Model(&diamond_m.DiamondPinkAccountDetail{}).
Where("user_id = ?", userId).
Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
return nil, myerr.WrapErr(err)
}
var cvDiamondDetails []*CvDiamondDetail
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
This diff is collapsed.
package user_cv package user_cv
import ( import (
"encoding/json"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
...@@ -69,6 +70,25 @@ type CvUserDetail struct { ...@@ -69,6 +70,25 @@ type CvUserDetail struct {
CountryManager *country_cv.CVCountryManager `json:"countryManager,omitempty"` // 国家管理员 CountryManager *country_cv.CVCountryManager `json:"countryManager,omitempty"` // 国家管理员
} }
type RoomInfoOwner struct {
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号
//是否VIP用户
IsVip bool `json:"isVip"`
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
Medals []uint32 `json:"medals"` // 勋章列表
Noble noble_cv.CvNoble `json:"noble"` // 当前的
WealthUserGrade uint32 `json:"wealthUserGrade"` //财富等级
CharmUserGrade uint32 `json:"charmUserGrade"` //魅力等级
MyGroupPowerName string `json:"myGroupPowerName"` // 当前用户所在势力绑定群组的名称
GroupPower GroupPower `json:"groupPower"` // 当前用户势力信息
}
type GroupPower struct { type GroupPower struct {
Id uint64 `json:"id"` // 群主所在的势力ID Id uint64 `json:"id"` // 群主所在的势力ID
Icon string `json:"icon"` // 家族头像 Icon string `json:"icon"` // 家族头像
...@@ -150,6 +170,45 @@ type CvUserExtend struct { ...@@ -150,6 +170,45 @@ type CvUserExtend struct {
ActiveGrade uint32 `json:"activityUserGrade"` ActiveGrade uint32 `json:"activityUserGrade"`
} }
type CvGroupMember struct {
//不会有返回值
Id *mysql.ID `json:"id,omitempty"`
//是否默认头像 true:是 false:不是
DefaultAvatar *bool `json:"defaultAvatar"`
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
//签名,不存在为nil
Description *string `json:"description"`
Birthday *uint64 `json:"birthday"`
//邀请码
Code *string `json:"code"`
//国家,不存在为nil
Country *string `json:"country"`
//国旗图标,不存在为nil
CountryIcon *string `json:"countryIcon"`
Sex *uint8 `json:"sex"`
//是否代理管理员, 只有自己查自己的时候才有值,其他情况为nil
IsAgentMgr *bool `json:"isAgentMgr"`
//是否展示年龄, 是本人才有数据,看其他用户均为nil
IsShowAge *uint8 `json:"isShowAge"`
//是否工会成员, 只有是自己查自己,这个才有值,其它全为nil, 20220329 数据开放:原因:产品1对1视频聊天中,公会用户视频需要送礼物。改为: 全部人可以知道是否是公会用户。
IsTradeUnion *bool `json:"isTradeUnion"`
//工会成员,是否开启了,匹配通知,只有 isTradeUnion值为true,这里才有值,
IsTradeUnionMatchNotification *bool `json:"isTradeUnionMatchNotification"`
//是否VIP用户
IsVip bool `json:"isVip"`
Ride property_cv.CvProperty `json:"ride"` // 当前使用的座驾
Noble noble_cv.CvNoble `json:"noble"` // 当前的
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
WealthGrade uint32 `json:"wealthUserGrade"`
CharmGrade uint32 `json:"charmUserGrade"`
ActiveGrade uint32 `json:"activityUserGrade"`
}
// 批量获取用户tiny信息 // 批量获取用户tiny信息
func GetUserTinyMap(userIds []mysql.ID) (map[mysql.ID]CvUserTiny, error) { func GetUserTinyMap(userIds []mysql.ID) (map[mysql.ID]CvUserTiny, error) {
userTinys, _, err := GetUserTinys(userIds) userTinys, _, err := GetUserTinys(userIds)
...@@ -849,17 +908,123 @@ func GetUserDetail(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*Cv ...@@ -849,17 +908,123 @@ func GetUserDetail(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*Cv
noble, superManagerMap[userId], myGroups, phoneInfo, thirdList, cvCountryManager) noble, superManagerMap[userId], myGroups, phoneInfo, thirdList, cvCountryManager)
} }
//群主信息
func GetRoomInfoOwner(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*CvUserDetail, error) {
model.Log.Infof("GetUserDetail %d begin", userId)
var user user_m.User
var err error
if err = mysql.Db.First(&user, userId).Error; err != nil {
return nil, myerr.WrapErr(err)
}
var wealthUserScore user_m.MatchWealthUserScore
if err := mysql.Db.Model(&user_m.MatchWealthUserScore{}).Where(&user_m.MatchWealthUserScore{UserId: userId}).First(&wealthUserScore).Error; err != nil {
if err != nil {
if err == gorm.ErrRecordNotFound {
wealthUserScore = user_m.MatchWealthUserScore{
UserId: userId,
Score: 0,
Grade: 0,
}
} else {
return nil, myerr.WrapErr(err)
}
}
}
var charmUserScore user_m.MatchCharmUserScore
if err := mysql.Db.Model(&user_m.MatchCharmUserScore{}).Where(&user_m.MatchCharmUserScore{
UserId: userId,
}).First(&charmUserScore).Error; err != nil {
if err != nil {
if err == gorm.ErrRecordNotFound {
charmUserScore = user_m.MatchCharmUserScore{
UserId: userId,
Score: 0,
Grade: 0,
}
} else {
return nil, myerr.WrapErr(err)
}
}
}
isVip, expireTime, err := user_m.IsVip(userId)
if err != nil {
return nil, myerr.WrapErr(err)
}
svip, err := rpc.GetUserSvip(model, userId)
if err != nil {
return nil, myerr.WrapErr(err)
}
medals := make(map[uint64][]uint32, 0)
medals[userId], err = user_m.GetUserMedalMerge(model.Log, mysql.Db, userId)
if err != nil {
return nil, err
}
medals, medalInfo, err := medal_cv.GetMedalInfoMap(mysql.Db, medals)
if err != nil {
return nil, err
}
groupPowerId, groupPowerName, err := groupPower_m.GetUserGroupPower(model, userId)
if err != nil {
return nil, err
}
powers := map[mysql.ID]uint64{userId: groupPowerId}
powerNames := map[mysql.ID]string{userId: groupPowerName}
groupPowerInfos, err := groupPower_m.MGetGroupPowerInfoMap(model, []mysql.ID{groupPowerId})
groupPowerGrades, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{groupPowerId})
groupPowerUsers, err := groupPower_m.MGetGroupPowerUsers(model, []mysql.ID{groupPowerId})
var memberMax int
grade := groupPowerGrades[groupPowerId].Grade
if grade >= groupPower_e.GroupPowerGrade0 && grade <= groupPower_e.GroupPowerGradeMax {
if grade == groupPower_e.GroupPowerGrade0 {
memberMax = 300
}
if grade == groupPower_e.GroupPowerGrade1 {
memberMax = 500
}
if grade == groupPower_e.GroupPowerGrade2 {
memberMax = 800
}
if grade == groupPower_e.GroupPowerGrade3 {
memberMax = 1200
}
}
memberNum := len(groupPowerUsers[groupPowerId])
if memberNum > memberMax {
memberMax = memberNum
}
groupPowerMembers := [2]int{memberNum, memberMax} // 0->memberNum 1->memberLimit
noble, err := noble_m.FindActiveNoble(mysql.Db, userId)
if err != nil {
return nil, err
}
return userToDetailOne(model, &user, myUserId, nil, false, false,
map[mysql.ID]Relation{}, isVip, expireTime, svip, nil, property_cv.CvProperty{}, wealthUserScore.Grade, charmUserScore.Grade,
0, medals[userId], medalInfo[userId], "", powers[userId], powerNames[userId], groupPowerInfos[groupPowerId], groupPowerGrades[groupPowerId], groupPowerMembers,
noble, false, nil, nil, nil, nil)
}
// 单用户版,简化参数 // 单用户版,简化参数
func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID, userTradeUnion *user_m.UserTradeUnion, isLike bool, likeMe bool, hvMap map[mysql.ID]Relation, func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID, userTradeUnion *user_m.UserTradeUnion, isLike bool, likeMe bool, hvMap map[mysql.ID]Relation,
isVip bool, vipExpireTime *int64, svip rpc.CvSvip, headwear *headwear_cv.CvHeadwear, ride property_cv.CvProperty, wealthGrade uint32, charmGrade uint32, activityGrade uint32, isVip bool, vipExpireTime *int64, svip rpc.CvSvip, headwear *headwear_cv.CvHeadwear, ride property_cv.CvProperty, wealthGrade uint32, charmGrade uint32, activityGrade uint32,
medals []uint32, medalInfo []medal_cv.CvMedal, room string, power uint64, powerName string, powerInfo groupPower_m.GroupPowerInfo, grade groupPower_m.GroupPowerGrade, members [2]int, noble *noble_m.UserNoble, isOfficialStaff bool, medals []uint32, medalInfo []medal_cv.CvMedal, room string, power uint64, powerName string, powerInfo groupPower_m.GroupPowerInfo, grade groupPower_m.GroupPowerGrade, members [2]int, noble *noble_m.UserNoble, isOfficialStaff bool,
myGroups []group_m.GroupInfo, phoneInfo *user_m.UserPhoneInfo, thirdList []int8, countryManager *country_cv.CVCountryManager) (*CvUserDetail, error) { myGroups []group_m.GroupInfo, phoneInfo *user_m.UserPhoneInfo, thirdList []int8, countryManager *country_cv.CVCountryManager) (*CvUserDetail, error) {
room, err := group_m.ToTxGroupId(model, room) if len(room) > 0 {
var err error
room, err = group_m.ToTxGroupId(model, room)
if err != nil { if err != nil {
model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err) model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err)
room = "" room = ""
} }
}
cvUserDetail := &CvUserDetail{ cvUserDetail := &CvUserDetail{
CvUserBase: CvUserBase{ CvUserBase: CvUserBase{
...@@ -1288,3 +1453,38 @@ func getMedalInfo(db *gorm.DB, medals []uint32) ([]uint32, []medal_cv.CvMedal, e ...@@ -1288,3 +1453,38 @@ func getMedalInfo(db *gorm.DB, medals []uint32) ([]uint32, []medal_cv.CvMedal, e
} }
return validMedals, medalInfo, nil return validMedals, medalInfo, nil
} }
func UserDetailToRoomInfoOwner(user *CvUserDetail) *RoomInfoOwner {
return &RoomInfoOwner{
Avatar: user.Avatar,
ExternalId: user.ExternalId,
Nick: user.Nick,
IsPrettyCode: user.IsPrettyCode,
IsVip: user.IsVip,
Svip: user.Svip,
Medals: user.Medals,
Noble: user.Noble,
WealthUserGrade: user.WealthUserGrade,
CharmUserGrade: user.CharmUserGrade,
MyGroupPowerName: user.MyGroupPowerName,
GroupPower: user.GroupPower,
}
}
type TopConsumersUser struct {
//不会有返回值
Id *mysql.ID `json:"id,omitempty"`
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
}
func CvUserExtendToCvGroupMember(detail CvUserExtend) CvGroupMember {
jData, _ := json.Marshal(detail)
res := CvGroupMember{}
_ = json.Unmarshal(jData, &res)
return res
}
...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code ...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS] [REDIS]
REDIS_HOST=47.244.34.27:6379 REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT] [JWT]
SECRET=hilo1632 SECRET=hilo1632
ISSUER_API=hiloApi ISSUER_API=hiloApi
......
...@@ -13,11 +13,14 @@ type gameAutoJoinMsg struct { ...@@ -13,11 +13,14 @@ type gameAutoJoinMsg struct {
Token string Token string
EnterType string EnterType string
GameCode string GameCode string
Is1V1 string
GameMode string
Is1V1Robot string
} }
func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, gameCode string) error { func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, gameCode, is1V1, gameMode, is1V1Robot string) error {
key := game_e.GetAutoMathEnterRoom(userId, imGroupId) key := game_e.GetAutoMathEnterRoom(userId, imGroupId)
info := gameAutoJoinMsg{traceId, token, enterType, gameCode} info := gameAutoJoinMsg{traceId, token, enterType, gameCode, is1V1, gameMode, is1V1Robot}
data, err := json.Marshal(info) data, err := json.Marshal(info)
if err != nil { if err != nil {
return err return err
...@@ -26,7 +29,7 @@ func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, g ...@@ -26,7 +29,7 @@ func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, g
if err != nil { if err != nil {
return err return err
} }
redisCli.GetRedis().Expire(context.Background(), key, time.Second*3) redisCli.GetRedis().Expire(context.Background(), key, time.Second*10)
return nil return nil
} }
......
package gift_c
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/domain/event/gift_ev"
"time"
)
const EventSendGiftHiloGroupQueue = "send:gift:queue:hilo_group"
// redis pop event sendGift
func BLPopQueueSendGift(model *domain.Model) *gift_ev.SendGiftEvent {
var res *gift_ev.SendGiftEvent
queue := EventSendGiftHiloGroupQueue
strs, err := model.RedisCluster.BLPop(model, time.Second, queue).Result()
if err != nil {
if err != redis.Nil {
model.Log.Errorf("BLPopQueueSendGift fail:%v", err)
}
return nil
}
if len(strs) >= 2 {
content := strs[1]
res = new(gift_ev.SendGiftEvent)
if err := json.Unmarshal([]byte(content), res); err != nil {
model.Log.Errorf("BLPopQueueSendGift json fail:%v", err)
return nil
}
return res
}
return nil
}
package groupPower_c
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/go-redis/redis/v8"
"github.com/jinzhu/now"
"github.com/pkg/errors"
"github.com/spf13/cast"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key/groupPower_k"
"time"
)
// 家族之星-排名
type GroupPowerStarRank struct {
Period string
GroupPowerId mysql.ID
UserId mysql.ID
Type groupPower_e.GroupPowerStarType
Score mysql.Num
}
// 增加家族之星分数
func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num) error {
ttl := map[string]time.Duration{
"day": time.Hour * 24 * 7,
"week": time.Hour * 24 * 7 * 30,
"month": time.Hour * 24 * 7 * 30 * 2,
}
for _, period := range []string{"day", "week", "month"} {
date := ""
switch period {
case "day":
date = time.Now().Format("2006-01-02")
case "week":
date = now.BeginningOfWeek().Format("2006-01-02")
case "month":
date = now.BeginningOfMonth().Format("2006-01-02")
}
key := groupPower_k.GetGroupPowerStarRankKey(_type, period, groupPowerId, date)
model.RedisCluster.ZIncrBy(model, key, float64(score), fmt.Sprintf("%d", userId))
model.RedisCluster.Expire(model, key, ttl[period])
}
return nil
}
// 获取家族之星排行
// param period: day|week|month
func GetGroupPowerStarRankPeriod(model *domain.Model, period string, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, targetDate ...string) ([]*GroupPowerStarRank, error) {
var res []*GroupPowerStarRank
date := ""
switch period {
case "day":
date = time.Now().Format("2006-01-02")
case "week":
date = now.BeginningOfWeek().Format("2006-01-02")
case "month":
date = now.BeginningOfMonth().Format("2006-01-02")
}
if len(date) <= 0 {
return res, errors.New("illegal date")
}
if len(targetDate) > 0 {
date = targetDate[0]
}
key := groupPower_k.GetGroupPowerStarRankKey(_type, period, groupPowerId, date)
rows, err := model.RedisCluster.ZRevRangeByScoreWithScores(model, key, &redis.ZRangeBy{
Min: "-inf",
Max: "+inf",
Offset: int64(offset),
Count: int64(limit),
}).Result()
if err != nil {
model.Log.Errorf("GetGroupPowerStarRankPeriod fail:%v", err)
return res, err
}
for _, v := range rows {
res = append(res, &GroupPowerStarRank{
Period: period,
GroupPowerId: groupPowerId,
UserId: cast.ToUint64(v.Member),
Type: _type,
Score: mysql.Num(v.Score),
})
}
return res, nil
}
// 获取家族之星三个排行榜的各自第一名
func GetGroupPowerMonthStartTop1(model *domain.Model, groupPowerId mysql.ID) ([]*GroupPowerStarRank, error) {
var res []*GroupPowerStarRank
r1, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeFamous, 0, 1)
if err != nil {
return res, err
}
r2, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeActive, 0, 1)
if err != nil {
return res, err
}
r3, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeCharm, 0, 1)
if err != nil {
return res, err
}
res = append(res, r1...)
res = append(res, r2...)
res = append(res, r3...)
return res, nil
}
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
"github.com/spf13/cast"
"hilo-group/_const/redis_key/group_k" "hilo-group/_const/redis_key/group_k"
"strconv" "strconv"
"time" "time"
...@@ -28,6 +29,7 @@ func ZAddUserEnterRoom(model *domain.Model, userId uint64, imGroupId string) { ...@@ -28,6 +29,7 @@ func ZAddUserEnterRoom(model *domain.Model, userId uint64, imGroupId string) {
} }
// 获取最近房间访客 // 获取最近房间访客
// 15天
func GetLastRoomVisitors(model *domain.Model, imGroupId string) (userIds []uint64) { func GetLastRoomVisitors(model *domain.Model, imGroupId string) (userIds []uint64) {
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId) groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
res, err := model.Redis.ZRangeByScore(model, groupKey, &redis.ZRangeBy{ res, err := model.Redis.ZRangeByScore(model, groupKey, &redis.ZRangeBy{
...@@ -47,16 +49,24 @@ func GetLastRoomVisitors(model *domain.Model, imGroupId string) (userIds []uint6 ...@@ -47,16 +49,24 @@ func GetLastRoomVisitors(model *domain.Model, imGroupId string) (userIds []uint6
} }
// 获取最近进入的房间 // 获取最近进入的房间
func GetUserRecentRooms(model *domain.Model, userId uint64) (imGroupIds []string) { // 3个月
func GetUserRecentRooms(model *domain.Model, userId uint64, offset, limit int64) (imGroupIds []string, roomEnterTime map[string]int64) {
roomEnterTime = make(map[string]int64)
userKey := group_k.GetUserEnterRoomUserKey(userId) userKey := group_k.GetUserEnterRoomUserKey(userId)
var err error res, err := model.Redis.ZRevRangeByScoreWithScores(model, userKey, &redis.ZRangeBy{
imGroupIds, err = model.Redis.ZRangeByScore(model, userKey, &redis.ZRangeBy{ Min: fmt.Sprintf("%d", time.Now().AddDate(0, -3, 0).Unix()),
Min: fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix()),
Max: "+inf", Max: "+inf",
Offset: offset,
Count: limit,
}).Result() }).Result()
if err != nil { if err != nil {
return return
} }
for _, v := range res {
imGroupId := cast.ToString(v.Member)
imGroupIds = append(imGroupIds, imGroupId)
roomEnterTime[imGroupId] = int64(v.Score)
}
return return
} }
...@@ -64,8 +74,10 @@ func GetUserRecentRooms(model *domain.Model, userId uint64) (imGroupIds []string ...@@ -64,8 +74,10 @@ func GetUserRecentRooms(model *domain.Model, userId uint64) (imGroupIds []string
// 15天前访问的 // 15天前访问的
func RemoveRoomVisitors(model *domain.Model, imGroupId string) { func RemoveRoomVisitors(model *domain.Model, imGroupId string) {
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId) groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
err := model.Redis.ZRemRangeByScore(model, groupKey, "-inf", fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix())).Err() n, err := model.Redis.ZRemRangeByScore(model, groupKey, "-inf", fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix())).Result()
if err != nil { if err != nil {
model.Log.Errorf("RemoveRoomVisitors fail:%v", err) model.Log.Errorf("RemoveRoomVisitors fail:%v", err)
} else {
model.Log.Infof("RemoveRoomVisitors key:%v,n:%v", groupKey, n)
} }
} }
...@@ -83,17 +83,17 @@ func SetGroupMemberTTL(groupId string, ttl time.Duration) (bool, error) { ...@@ -83,17 +83,17 @@ func SetGroupMemberTTL(groupId string, ttl time.Duration) (bool, error) {
func GetGroupConsume(groupId string) (uint64, error) { func GetGroupConsume(groupId string) (uint64, error) {
key := getGroupConsumeKey(groupId) key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Get(context.Background(), key).Uint64() return redisCli.RedisClusterClient.Get(context.Background(), key).Uint64()
} }
func SetGroupConsume(groupId string, consume uint64, ttl time.Duration) error { func SetGroupConsume(groupId string, consume uint64, ttl time.Duration) error {
key := getGroupConsumeKey(groupId) key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Set(context.Background(), key, consume, ttl).Err() return redisCli.RedisClusterClient.Set(context.Background(), key, consume, ttl).Err()
} }
func ClearGroupConsume(groupId string) error { func ClearGroupConsume(groupId string) error {
key := getGroupConsumeKey(groupId) key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Del(context.Background(), key).Err() return redisCli.RedisClusterClient.Del(context.Background(), key).Err()
} }
// 增加编辑用户cd // 增加编辑用户cd
......
package mic_c
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/mic_ev"
"time"
)
// redis queue on mic
func QueueOnMic(model *domain.Model, onMic *mic_ev.OnMicEvent) error {
queue := mic_k.GetOnMicQueue()
onMic.Ts = time.Now().UnixNano() // 给一个时间戳
body, _ := json.Marshal(onMic)
return model.RedisCluster.RPush(model, queue, string(body)).Err()
}
// redis pop on mic
func BLPopQueueOnMic(model *domain.Model) *mic_ev.OnMicEvent {
var res *mic_ev.OnMicEvent
queue := mic_k.GetOnMicQueue()
strs, err := model.RedisCluster.BLPop(model, time.Second, queue).Result()
if err != nil {
if err != redis.Nil {
model.Log.Errorf("BLPopQueueOnMic fail:%v", err)
}
return nil
}
if len(strs) >= 2 {
content := strs[1]
res = new(mic_ev.OnMicEvent)
if err := json.Unmarshal([]byte(content), res); err != nil {
model.Log.Errorf("BLPopQueueOnMic json fail:%v", err)
return nil
}
return res
}
return nil
}
...@@ -27,17 +27,17 @@ func SetJSON(model *domain.Model, key string, obj interface{}) (err error) { ...@@ -27,17 +27,17 @@ func SetJSON(model *domain.Model, key string, obj interface{}) (err error) {
if err != nil { if err != nil {
return err return err
} }
return model.Redis.Set(model.Context, key, value, DEFAULT_TTL).Err() return model.RedisCluster.Set(model.Context, key, value, DEFAULT_TTL).Err()
} }
// 获取redis中json结构体 // 获取redis中json结构体
// return err: may redisV8.Nil // return err: may redisV8.Nil
func GetJSON(model *domain.Model, key string, obj interface{}) (err error) { func GetJSON(model *domain.Model, key string, obj interface{}) (err error) {
var value []byte var value []byte
defer func() { //defer func() {
model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err) // model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err)
}() //}()
value, err = model.Redis.Get(model.Context, key).Bytes() value, err = model.RedisCluster.Get(model.Context, key).Bytes()
if err != nil { if err != nil {
// may redisV2.Nil // may redisV2.Nil
return return
...@@ -59,7 +59,7 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time ...@@ -59,7 +59,7 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
if time.Now().After(deadline) { if time.Now().After(deadline) {
return false return false
} }
flag, err := model.Redis.SetNX(model, key, "1", expireTimeout).Result() flag, err := model.RedisCluster.SetNX(model, key, "1", expireTimeout).Result()
if err != nil || !flag { if err != nil || !flag {
time.Sleep(time.Millisecond * 10) time.Sleep(time.Millisecond * 10)
} else { } else {
...@@ -70,5 +70,5 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time ...@@ -70,5 +70,5 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
// 解锁 // 解锁
func UnLock(model *domain.Model, key string) { func UnLock(model *domain.Model, key string) {
model.Redis.Del(model, key) model.RedisCluster.Del(model, key)
} }
package res_c package res_c
import ( import (
"context"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"hilo-group/_const/redis_key" "github.com/bluele/gcache"
"hilo-group/domain/model/res_m" "hilo-group/domain/model/res_m"
"time" "time"
) )
// 统一改成lru
var countryIconLru = gcache.New(1000).LRU().Build()
var countryIconKey = "country:icon"
var countryAreaLru = gcache.New(1000).LRU().Build()
var countryAreaKey = "country:area"
func GetCountryIconMap(model *domain.Model) (map[string]string, error) { func GetCountryIconMap(model *domain.Model) (map[string]string, error) {
m, err := GetAllCountryIcon(model) m, err := GetAllCountryIcon(model)
if err != nil || len(m) <= 0 { if err != nil || len(m) <= 0 {
...@@ -24,17 +30,22 @@ func GetCountryIconMap(model *domain.Model) (map[string]string, error) { ...@@ -24,17 +30,22 @@ func GetCountryIconMap(model *domain.Model) (map[string]string, error) {
} }
func GetAllCountryIcon(model *domain.Model) (map[string]string, error) { func GetAllCountryIcon(model *domain.Model) (map[string]string, error) {
key := redis_key.GetCountryIconKey() //key := redis_key.GetCountryIconKey()
return model.Redis.HGetAll(context.Background(), key).Result() if data, err := countryIconLru.Get(countryIconKey); err == nil {
return data.(map[string]string), nil
}
//return model.Redis.HGetAll(context.Background(), key).Result()
return map[string]string{}, nil
} }
func SaveAllCountryIcon(model *domain.Model, icons map[string]string) (int64, error) { func SaveAllCountryIcon(model *domain.Model, icons map[string]string) {
key := redis_key.GetCountryIconKey() //key := redis_key.GetCountryIconKey()
ret, err := model.Redis.HSet(context.Background(), key, icons).Result() //ret, err := model.Redis.HSet(context.Background(), key, icons).Result()
if err == nil { //if err == nil {
model.Redis.Expire(context.Background(), key, time.Minute*10) // model.Redis.Expire(context.Background(), key, time.Minute*10)
} //}
return ret, err //return ret, err
_ = countryIconLru.SetWithExpire(countryIconKey, icons, time.Minute*10)
} }
func GetCountryAreaMap(model *domain.Model) (map[string]string, error) { func GetCountryAreaMap(model *domain.Model) (map[string]string, error) {
...@@ -53,15 +64,20 @@ func GetCountryAreaMap(model *domain.Model) (map[string]string, error) { ...@@ -53,15 +64,20 @@ func GetCountryAreaMap(model *domain.Model) (map[string]string, error) {
} }
func GetAllCountryArea(model *domain.Model) (map[string]string, error) { func GetAllCountryArea(model *domain.Model) (map[string]string, error) {
key := redis_key.GetCountryAreaKey() //key := redis_key.GetCountryAreaKey()
return model.Redis.HGetAll(context.Background(), key).Result() //return model.Redis.HGetAll(context.Background(), key).Result()
if data, err := countryAreaLru.Get(countryAreaKey); err == nil {
return data.(map[string]string), nil
}
return map[string]string{}, nil
} }
func SaveAllCountryArea(model *domain.Model, data map[string]string) (int64, error) { func SaveAllCountryArea(model *domain.Model, data map[string]string) {
key := redis_key.GetCountryAreaKey() //key := redis_key.GetCountryAreaKey()
ret, err := model.Redis.HSet(context.Background(), key, data).Result() //ret, err := model.Redis.HSet(context.Background(), key, data).Result()
if err == nil { //if err == nil {
model.Redis.Expire(context.Background(), key, time.Minute*10) // model.Redis.Expire(context.Background(), key, time.Minute*10)
} //}
return ret, err //return ret, err
_ = countryAreaLru.SetWithExpire(countryAreaKey, data, time.Minute*10)
} }
...@@ -2,42 +2,44 @@ package room_c ...@@ -2,42 +2,44 @@ package room_c
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/redisCli" "git.hilo.cn/hilo-common/resource/redisCli"
"github.com/bluele/gcache"
redis2 "github.com/go-redis/redis/v8" redis2 "github.com/go-redis/redis/v8"
"github.com/spf13/cast"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"strconv" "hilo-group/_const/redis_key/group_k"
"time" "time"
) )
// 处理访问房间的相关缓存 // 处理访问房间的相关缓存
func ProcessRoomVisit(groupId string, userId uint64) error { func ProcessRoomVisit(groupId string, userId uint64) error {
key := redis_key.GetPrefixGroupInUserDuration(groupId) //key := redis_key.GetPrefixGroupInUserDuration(groupId)
now := time.Now() //now := time.Now()
ret, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{ //ret, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
Score: float64(now.Unix()), // Score: float64(now.Unix()),
Member: userId, // Member: userId,
}).Result() //}).Result()
if err != nil { //if err != nil {
return err // return err
} //}
mylogrus.MyLog.Infof("ProcessRoomVisit, ZADD %s, return %d", key, ret) //mylogrus.MyLog.Infof("ProcessRoomVisit, ZADD %s, return %d", key, ret)
//
// 每群定时清一次数据可以了 //// 每群定时清一次数据可以了
if now.Second()%redis_key.GroupInDurationClearPeriod == 0 { //if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
rc, err := clearRoomVisit(groupId, now.AddDate(0, 0, -redis_key.GroupInDurationTTL)) // rc, err := clearRoomVisit(groupId, now.AddDate(0, 0, -redis_key.GroupInDurationTTL))
if err == nil { // if err == nil {
mylogrus.MyLog.Infof("ProcessRoomVisit, clearRoomVisit %s, return %d", key, rc) // mylogrus.MyLog.Infof("ProcessRoomVisit, clearRoomVisit %s, return %d", key, rc)
} else { // } else {
mylogrus.MyLog.Warnf("ProcessRoomVisit, clearRoomVisit %s, failed %s", key, err.Error()) // mylogrus.MyLog.Warnf("ProcessRoomVisit, clearRoomVisit %s, failed %s", key, err.Error())
} // }
} //}
// 马上更新roomVisitCount // 马上更新roomVisitCount
if _, err := GetSetRoomVisitCount(groupId); err != nil { if _, err := GetSetRoomVisitCount(groupId); err != nil {
mylogrus.MyLog.Warnf("ProcessRoomVisit, failed for key %s, err: %s", key, err.Error()) mylogrus.MyLog.Errorf("ProcessRoomVisit, failed for groupId %s, err: %s", groupId, err.Error())
} }
return nil return nil
...@@ -59,15 +61,17 @@ func ProcessUserRoomVisit(userId uint64, groupId string) error { ...@@ -59,15 +61,17 @@ func ProcessUserRoomVisit(userId uint64, groupId string) error {
} }
// 查询用户访问过的房间及其时间 // 查询用户访问过的房间及其时间
// todo 去掉查询,redis性能
func GetUserRoomVisit(userId uint64) (map[string]int64, error) { func GetUserRoomVisit(userId uint64) (map[string]int64, error) {
result := make(map[string]int64, 0)
return result, nil
key := redis_key.GetUserEnterRoomKey(userId) key := redis_key.GetUserEnterRoomKey(userId)
ret, err := redisCli.GetRedis().ZRangeWithScores(context.Background(), key, 0, -1).Result() ret, err := redisCli.GetRedis().ZRangeWithScores(context.Background(), key, 0, -1).Result()
if err != nil { if err != nil {
return nil, err return nil, err
} }
mylogrus.MyLog.Infof("GetUserRoomVisit, ZRangeWithScores %s, return %v", key, ret) //mylogrus.MyLog.Infof("GetUserRoomVisit, ZRangeWithScores %s, return %v", key, ret)
result := make(map[string]int64, 0)
for _, i := range ret { for _, i := range ret {
result[i.Member.(string)] = int64(i.Score) result[i.Member.(string)] = int64(i.Score)
} }
...@@ -75,53 +79,63 @@ func GetUserRoomVisit(userId uint64) (map[string]int64, error) { ...@@ -75,53 +79,63 @@ func GetUserRoomVisit(userId uint64) (map[string]int64, error) {
} }
// 批量获取房间访问人数 // 批量获取房间访问人数
// 带上lru
var roomVisitCountLru = gcache.New(100).LRU().Build()
func MGetRoomVisitCount(groupIds []string) (map[string]string, error) { func MGetRoomVisitCount(groupIds []string) (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
visit := make(map[string]string) visit := make(map[string]string)
if len(groupIds) <= 0 { if len(groupIds) <= 0 {
return visit, nil return visit, nil
} }
res, err := redisCli.GetRedis().HMGet(context.Background(), key, groupIds...).Result() lKey := "room:visit:count"
if err != nil { if data, err := roomVisitCountLru.Get(lKey); err == nil {
return visit, err return data.(map[string]string), nil
} }
if len(res) != len(groupIds) { // 用redisCluster中的zset代替,只是取出大于10的
return visit, errors.New(fmt.Sprintf("MGetRoomVisitCount fail,miss match len,%v-%v", len(res), len(groupIds))) zKey := redis_key.GetPrefixRoomVisitCountZset()
cnt := 10
if !config.AppIsRelease() {
cnt = 0
} }
for i, groupId := range groupIds { zRes, err := redisCli.GetClusterRedis().ZRevRangeByScoreWithScores(context.Background(), zKey, &redis2.ZRangeBy{
if cnt, ok := res[i].(string); ok { Min: fmt.Sprintf("%d", cnt),
visit[groupId] = cnt Max: "+inf",
}).Result()
if err != nil {
mylogrus.MyLog.Errorf("MGetRoomVisitCount zset fail:%v", err)
return visit, err
} }
for _, v := range zRes {
visit[cast.ToString(v.Member)] = cast.ToString(v.Score)
} }
_ = roomVisitCountLru.SetWithExpire(lKey, visit, time.Minute*15)
return visit, nil return visit, nil
} }
func GetSetRoomVisitCount(groupId string) (int64, error) { func GetSetRoomVisitCount(groupId string) (int64, error) {
key := redis_key.GetPrefixGroupInUserDuration(groupId) //key := redis_key.GetPrefixGroupInUserDuration(groupId)
key := group_k.GetUserEnterRoomGroupKey(groupId)
vc, err := redisCli.GetRedis().ZCard(context.Background(), key).Result() vc, err := redisCli.GetRedis().ZCard(context.Background(), key).Result()
// 查到合法值后,更新二级缓存 // 查到合法值后,更新二级缓存
if err == nil && vc >= 0 { if err == nil && vc >= 0 {
ret, err := saveRoomVisitCount(groupId, vc) if err := saveRoomVisitCount(groupId, vc); err != nil {
mylogrus.MyLog.Infof("saveRoomVisitCount %s, ret = %d, err: %v", groupId, ret, err) mylogrus.MyLog.Errorf("saveRoomVisitCount %s, err: %v", groupId, err)
}
} }
return vc, err return vc, err
} }
func saveRoomVisitCount(groupId string, count int64) (int64, error) { func saveRoomVisitCount(groupId string, count int64) error {
key := redis_key.GetPrefixRoomVisitCount() //key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result() zKey := redis_key.GetPrefixRoomVisitCountZset()
} // zset同步存一份到redis集群
if err := redisCli.GetClusterRedis().ZAdd(context.Background(), zKey, &redis2.Z{
func clearRoomVisit(groupId string, t time.Time) (int64, error) { Score: float64(count),
value := strconv.FormatInt(t.Unix(), 10) Member: groupId,
ret, err := redisCli.GetRedis().ZRemRangeByScore(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId), "0", value).Result() }).Err(); err != nil {
if err != nil { mylogrus.MyLog.Errorf("GetPrefixRoomVisitCountZset fail %s", err.Error())
return 0, err return err
} }
return ret, nil return nil
} //return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result()
func GetAllRoomVisitCount() (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HGetAll(context.Background(), key).Result()
} }
package user_c
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"sync"
"time"
)
type UserLevel struct {
UserId mysql.ID
Level int
}
var svipVipNobleLock sync.RWMutex
var svipLevel = make(map[mysql.ID]int) // userId->svipLevel
var nobleLevel = make(map[mysql.ID]uint16) // userId->nobleLevel
var userVips = make(map[mysql.ID]bool) // userId->isVip
// 加载数据到lru
func LoadAllSvipVipNoble(model *domain.Model) {
start := time.Now()
var svips []UserLevel
svipMap := make(map[mysql.ID]int)
if err := model.DB().Table("user_svip").Select("user_id,level").Where("level > 0").Find(&svips).Error; err != nil {
model.Log.Errorf("LoadAllSvip fail:%v", err)
} else {
for _, v := range svips {
svipMap[v.UserId] = v.Level
}
}
var nobles []UserLevel
nobleMap := make(map[mysql.ID]uint16)
if err := model.DB().Table("user_noble").Select("user_id,MAX(level) level").
Where("level > 0 AND end_time > ?", time.Now()).Group("user_id").Find(&nobles).Error; err != nil {
model.Log.Errorf("LoadAllNoble fail:%v", err)
} else {
for _, v := range nobles {
nobleMap[v.UserId] = uint16(v.Level)
}
}
var vips []UserLevel
vipMap := make(map[mysql.ID]bool)
if err := model.DB().Table("user_vip").Select("user_id").
Where("expire_at > ?", time.Now()).Find(&vips).Error; err != nil {
model.Log.Errorf("LoadAllVip fail:%v", err)
} else {
for _, v := range vips {
vipMap[v.UserId] = true
}
}
// 上锁赋值
svipVipNobleLock.Lock()
svipLevel = svipMap
nobleLevel = nobleMap
userVips = vipMap
svipVipNobleLock.Unlock()
model.Log.Infof("LoadAllSvipVipNoble svip:%v,vip:%v,noble:%v,cost:%vs", len(svipMap), len(vipMap), len(nobleMap), time.Now().Sub(start).Seconds())
}
func BatchGetNobleLevel(model *domain.Model, userIds []uint64) map[uint64]uint16 {
res := make(map[uint64]uint16)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
res[userId] = nobleLevel[userId]
}
return res
}
func MGetUserSvipLevel(model *domain.Model, userIds []uint64) map[uint64]int {
res := make(map[uint64]int)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
res[userId] = svipLevel[userId]
}
return res
}
func BatchGetVips(model *domain.Model, userIds []uint64) map[uint64]*int64 {
res := make(map[uint64]*int64)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
vip := int64(1)
if userVips[userId] {
res[userId] = &vip
}
}
return res
}
...@@ -38,6 +38,36 @@ func GetUserTinyById(model *domain.Model, userId mysql.ID) (*user_m.UserTiny, er ...@@ -38,6 +38,36 @@ func GetUserTinyById(model *domain.Model, userId mysql.ID) (*user_m.UserTiny, er
return userTiny, nil return userTiny, nil
} }
// 获取用户简要信息
// param userId 用户id
func MGetUserTinyById(model *domain.Model, userIds []mysql.ID) []*user_m.UserTiny {
var users []*user_m.UserTiny
for _, userId := range userIds {
if user, _ := GetUserTinyById(model, userId); user != nil {
users = append(users, user)
}
}
return users
}
// 获取用户externalIds
// return []externalIds map[userId]extId map[userId]code
func GetUserExternalIds(model *domain.Model, userIds []mysql.ID) ([]string, map[uint64]string, map[uint64]string) {
var res []string
var m = make(map[uint64]string)
var c = make(map[uint64]string)
if len(userIds) <= 0 {
return res, m, c
}
users := MGetUserTinyById(model, userIds)
for _, u := range users {
res = append(res, u.ExternalId)
m[u.ID] = u.ExternalId
c[u.ID] = u.Code
}
return res, m, c
}
// 获取用户简要信息By ExternalId // 获取用户简要信息By ExternalId
func GetUserByExternalId(model *domain.Model, externalId mysql.Str) (*user_m.UserTiny, error) { func GetUserByExternalId(model *domain.Model, externalId mysql.Str) (*user_m.UserTiny, error) {
userId, err := ToUserId(model, externalId) userId, err := ToUserId(model, externalId)
...@@ -52,7 +82,7 @@ func ToUserId(model *domain.Model, externalId mysql.Str) (mysql.ID, error) { ...@@ -52,7 +82,7 @@ func ToUserId(model *domain.Model, externalId mysql.Str) (mysql.ID, error) {
if externalId == "" { if externalId == "" {
return 0, myerr.NewSysError("externalId 不能为空") return 0, myerr.NewSysError("externalId 不能为空")
} }
userId, err := model.Redis.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64() userId, err := model.RedisCluster.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64()
if err != nil && err != redisV8.Nil { if err != nil && err != redisV8.Nil {
return 0, err return 0, err
} }
...@@ -75,7 +105,7 @@ func ToUserIdByCode(model *domain.Model, code mysql.Str) (mysql.ID, error) { ...@@ -75,7 +105,7 @@ func ToUserIdByCode(model *domain.Model, code mysql.Str) (mysql.ID, error) {
if code == "" { if code == "" {
return 0, myerr.NewSysError("code 不能为空") return 0, myerr.NewSysError("code 不能为空")
} }
userId, err := model.Redis.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64() userId, err := model.RedisCluster.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64()
if err != nil && err != redisV8.Nil { if err != nil && err != redisV8.Nil {
return 0, err return 0, err
} }
...@@ -104,11 +134,11 @@ func cacheUserTiny(model *domain.Model, user *user_m.User) error { ...@@ -104,11 +134,11 @@ func cacheUserTiny(model *domain.Model, user *user_m.User) error {
// return err // return err
//} //}
// cache externalId->userId // cache externalId->userId
if err := model.Redis.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil { if err := model.RedisCluster.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
return err return err
} }
// cache code->userId // cache code->userId
if err := model.Redis.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil { if err := model.RedisCluster.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
return err return err
} }
if err := cache.SetJSON(model, user_k.GetUserTinyKey(user.ID), userTiny); err != nil { if err := cache.SetJSON(model, user_k.GetUserTinyKey(user.ID), userTiny); err != nil {
......
package group_ev
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
)
var txGroupInListen = new(domain.EventBase)
// 进房事件
type TxGroupInEvent struct {
GroupId string // imGroupId
UserId mysql.ID
ExternalId string
Nick string
Avatar string
IsMember bool //是否永久成员
IsVip bool
NobleLevel uint16
}
func AddTxGroupInEventSync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventSync(txGroupInListen, callback)
}
func AddTxGroupInEventAsync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventAsync(txGroupInListen, callback)
}
func PublishTxGroupInEvent(model *domain.Model, event interface{}) error {
return domain.PublishEvent(txGroupInListen, model, event)
}
...@@ -14,6 +14,8 @@ type OnMicEvent struct { ...@@ -14,6 +14,8 @@ type OnMicEvent struct {
UserId uint64 // 麦中的人 UserId uint64 // 麦中的人
Forbid bool // 静音 true:静音,false:没有静音 Forbid bool // 静音 true:静音,false:没有静音
Timestamp int64 // 上麦的的时间戳 Timestamp int64 // 上麦的的时间戳
Ts int64
} }
func AddOnMicEventSync(callback func(model *domain.Model, event interface{}) error) { func AddOnMicEventSync(callback func(model *domain.Model, event interface{}) error) {
......
package common package common
import ( import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/utils" "git.hilo.cn/hilo-common/utils"
"hilo-group/_const/redis_key" "github.com/bluele/gcache"
"hilo-group/myerr"
"time" "time"
) )
func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) { // 改成lru
bData, err := GetCache(redis_key.GetUserMedalMerge(userId)) var userMedalMergeLru = gcache.New(10000).LRU().Build()
if err != nil {
return nil, myerr.WrapErr(err)
}
res := make([]uint32, 0) func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) {
err = json.Unmarshal(bData, &res) if data, err := userMedalMergeLru.Get(userId); err == nil {
if err != nil { return data.([]uint32), nil
return nil, myerr.WrapErr(err)
} }
return res, nil return nil, nil
} }
func SetUserMedalMergeCache(userId mysql.ID, data []uint32) error { func SetUserMedalMergeCache(userId mysql.ID, data []uint32) {
err := SetCache(redis_key.GetUserMedalMerge(userId), data, time.Hour*2) _ = userMedalMergeLru.SetWithExpire(userId, data, time.Minute*15)
if err != nil {
mylogrus.MyLog.Errorf("SetUserMedalMerge err:%s", err)
return myerr.WrapErr(err)
}
return nil
} }
// 删除勋章缓存, 延迟删除 // 删除勋章缓存, 延迟删除
...@@ -44,41 +30,6 @@ func DelUserMedalMergeCacheDelay(userId mysql.ID) { ...@@ -44,41 +30,6 @@ func DelUserMedalMergeCacheDelay(userId mysql.ID) {
}() }()
} }
func DelUserMedalMergeCache(userId mysql.ID) error { func DelUserMedalMergeCache(userId mysql.ID) {
err := DelCache(redis_key.GetUserMedalMerge(userId)) userMedalMergeLru.Remove(userId)
if err != nil {
mylogrus.MyLog.Errorf("DetUserMedalMerge err:%s, userId:%v", err, userId)
return myerr.WrapErr(err)
}
return nil
}
func DelCache(key string) error {
err := redisCli.GetRedis().Del(context.Background(), key).Err()
if err != nil {
mylogrus.MyLog.Errorf("DelCache key:%s, err:%s", key, err)
return err
}
return nil
}
func GetCache(key string) ([]byte, error) {
data, err := redisCli.GetRedis().Get(context.Background(), key).Bytes()
if err != nil {
return nil, err
}
return data, nil
}
func SetCache(key string, data interface{}, expire time.Duration) error {
jData, err := json.Marshal(data)
if err != nil {
return err
}
err = redisCli.GetRedis().Set(context.Background(), key, jData, expire).Err()
if err != nil {
mylogrus.MyLog.Errorf("SetCache key:%s, data:%v, err:%s", key, data, err)
return err
}
return nil
} }
package diamond_m package diamond_m
import ( import (
"fmt"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils" "git.hilo.cn/hilo-common/utils"
"gorm.io/gorm" "gorm.io/gorm"
"hilo-group/_const/enum/diamond_e" "hilo-group/_const/enum/diamond_e"
"hilo-group/domain/model"
"hilo-group/myerr" "hilo-group/myerr"
"hilo-group/myerr/bizerr" "hilo-group/myerr/bizerr"
"strconv" "strconv"
...@@ -40,6 +40,11 @@ type DiamondAccountDetail struct { ...@@ -40,6 +40,11 @@ type DiamondAccountDetail struct {
diamondAccount *DiamondAccount `gorm:"-"` diamondAccount *DiamondAccount `gorm:"-"`
} }
func (DiamondAccountDetail) TableName() string {
month := time.Now().Format("200601")
return fmt.Sprintf("diamond_account_detail_%s", month)
}
// 粉钻详情 // 粉钻详情
type DiamondPinkAccountDetail struct { type DiamondPinkAccountDetail struct {
mysql.Entity mysql.Entity
...@@ -110,7 +115,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon ...@@ -110,7 +115,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
var count int64 var count int64
if diamondOperateSet.FrequencyDay == -1 { if diamondOperateSet.FrequencyDay == -1 {
if diamondOperateSet.FrequencyNum != -1 { if diamondOperateSet.FrequencyNum != -1 {
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{ diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId, UserId: diamondAccount.UserId,
OperateType: operateType, OperateType: operateType,
}).Count(&count) }).Count(&count)
...@@ -125,7 +130,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon ...@@ -125,7 +130,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
//一天的次数 //一天的次数
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{ diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId, UserId: diamondAccount.UserId,
OperateType: operateType, OperateType: operateType,
}).Where("created_time >= ? ", beginTime).Count(&count) }).Where("created_time >= ? ", beginTime).Count(&count)
...@@ -133,7 +138,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon ...@@ -133,7 +138,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, bizerr.DiamondFrequency return nil, bizerr.DiamondFrequency
} }
//终极拦截,利用 //终极拦截,利用
diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from diamond_account_detail d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )") diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from " + DiamondAccountDetail{}.TableName() + " d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )")
} }
//-1,代表值无效,由参数给与 //-1,代表值无效,由参数给与
...@@ -197,7 +202,10 @@ func (diamondAccountDetail *DiamondAccountDetail) PersistentNoInTransactional() ...@@ -197,7 +202,10 @@ func (diamondAccountDetail *DiamondAccountDetail) PersistentNoInTransactional()
} }
//持久化diamondAccountDetail //持久化diamondAccountDetail
if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil { //if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
// return myerr.WrapErr(err)
//}
if err := diamondAccountDetail.DB().Table(diamondAccountDetail.TableName()).Save(diamondAccountDetail).Error; err != nil {
return myerr.WrapErr(err) return myerr.WrapErr(err)
} }
//改变diamondAccount值 //改变diamondAccount值
...@@ -245,7 +253,10 @@ func (diamondAccountDetail *DiamondAccountDetail) Persistent() error { ...@@ -245,7 +253,10 @@ func (diamondAccountDetail *DiamondAccountDetail) Persistent() error {
} }
//持久化diamondAccountDetail //持久化diamondAccountDetail
if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil { //if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
// return myerr.WrapErr(err)
//}
if err := diamondAccountDetail.DB().Table(diamondAccountDetail.TableName()).Save(diamondAccountDetail).Error; err != nil {
return myerr.WrapErr(err) return myerr.WrapErr(err)
} }
//改变diamondAccount值 //改变diamondAccount值
......
package event_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
)
// 进房事件消息
type EventGroupIn struct {
mysql.Entity
*domain.Model `gorm:"-"`
Proto mysql.Type
Payload []byte
Mark mysql.YesNo
MarkHiloGroup mysql.YesNo
}
func (EventGroupIn) TableName() string {
return "event_group_in"
}
// 偏移值
type EventGroupInOffsetHiloGroup struct {
mysql.Entity
*domain.Model `gorm:"-"`
MarkOffset mysql.ID
}
// 获取当前偏移值
func GroupOffset(model *domain.Model) (*EventGroupInOffsetHiloGroup, error) {
offset := new(EventGroupInOffsetHiloGroup)
if err := model.Db.WithContext(model).First(offset).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("Offset fail:%v", err)
return nil, err
}
// gorm.ErrRecordNotFound
}
offset.Model = model
return offset, nil
}
// 批量获取进房事件
func FetchEventGroupIn(model *domain.Model, limit int) ([]*EventGroupIn, *EventGroupInOffsetHiloGroup, error) {
offset, err := GroupOffset(model)
if err != nil {
return nil, nil, err
}
var events []*EventGroupIn
if err := model.Db.WithContext(model).Model(EventGroupIn{}).
Where("id > ?", offset.MarkOffset).
Order("id asc").Limit(limit).Find(&events).Error; err != nil {
model.Log.Errorf("FetchEventGroupIn fail:%v", err)
return nil, nil, err
}
return events, offset, nil
}
// 标记已完成
func (p *EventGroupIn) MarkDone() error {
p.MarkHiloGroup = mysql.YES
return p.Db.WithContext(p.Model).Model(EventGroupIn{}).Where("id = ?", p.ID).Update("mark_hilo_group", p.MarkHiloGroup).Limit(1).Error
}
...@@ -9,3 +9,7 @@ func (p *EventGiftSendOffsetHiloGroup) Persistence() error { ...@@ -9,3 +9,7 @@ func (p *EventGiftSendOffsetHiloGroup) Persistence() error {
func (p *EventGiftSend) Persistence() error { func (p *EventGiftSend) Persistence() error {
return model.Persistent(p.Db, p) return model.Persistent(p.Db, p)
} }
func (p *EventGroupInOffsetHiloGroup) Persistence() error {
return model.Persistent(p.Db, p)
}
\ No newline at end of file
...@@ -31,6 +31,7 @@ type GameInfo struct { ...@@ -31,6 +31,7 @@ type GameInfo struct {
type GameConfig struct { type GameConfig struct {
Ludo *GameConfigDiamond `json:"ludo"` Ludo *GameConfigDiamond `json:"ludo"`
Uno *GameConfigDiamond `json:"uno"` Uno *GameConfigDiamond `json:"uno"`
Domino *GameConfigDiamond `json:"domino"`
} }
type GameConfigDiamond struct { type GameConfigDiamond struct {
......
...@@ -127,6 +127,40 @@ func (g *GiftOperate) GetConsumeByRange(beginTime, endTime time.Time) (uint32, u ...@@ -127,6 +127,40 @@ func (g *GiftOperate) GetConsumeByRange(beginTime, endTime time.Time) (uint32, u
if len(rows) <= 0 { if len(rows) <= 0 {
return 0, 0, nil return 0, 0, nil
} }
//if beginTime.Unix() >= 1691337600 && beginTime.Unix() < 1691942400 { // 因为这周水果机被部分人刷币,所以这里做了特殊的处理
// reduceMap := map[string]uint64{
// "HTGS#a63226380": 20000000,
// //"HTGS#a42641278": 10000000,
// "@TGS#3ZZ5GZLHA": 27141539,
// "HTGS#a81630128": 8955410,
// "HTGS#a42300598": 50211301,
// "HTGS#a40088696": 10000000,
// "HTGS#a21700997": 14352310,
// "HTGS#a83608384": 49644203,
// "@TGS#33GDXTSIH": 50000000,
// "HTGS#a50538513": 15000000,
// "HTGS#a77282385": 15000000,
// "HTGS#a59437326": 10000000,
// "HTGS#a16909405": 10000000,
// "HTGS#a44104431": 16861206,
// "HTGS#a56794634": 59591313,
// "HTGS#a11286025": 31232311,
// "HTGS#a17238550": 52309338,
// "HTGS#a83592361": 79545067,
// "HTGS#a39882521": 10255093,
// }
// if reduceNum, ok := reduceMap[g.SceneUid]; ok {
// if g.Log != nil {
// g.Log.Infof("fruit diamond reduceMap,groupId:%v,reduceNum:%v", g.SceneUid, reduceNum)
// }
// if rows[0].Consume >= reduceNum {
// rows[0].Consume -= reduceNum
// } else {
// rows[0].Consume = 0
// }
// }
//}
return rows[0].C, rows[0].Consume, nil return rows[0].C, rows[0].Consume, nil
} }
...@@ -148,6 +182,17 @@ func (g *GiftOperate) BatchGetConsumeByRange(beginTime, endTime time.Time) ([]Sc ...@@ -148,6 +182,17 @@ func (g *GiftOperate) BatchGetConsumeByRange(beginTime, endTime time.Time) ([]Sc
return rows, nil return rows, nil
} }
func (g *GiftOperate) BatchGetSupportList(model *domain.Model, beginTime, endTime time.Time) ([]uint64, error) {
userIds := make([]uint64, 0)
err := model.DB().Model(g).
Select("DISTINCT(send_user_id) AS user_id").
Where(g).Where("created_time BETWEEN ? AND ?", beginTime, endTime).Pluck("user_id", &userIds).Error
if err != nil {
return nil, err
}
return userIds, nil
}
func SumSendGift(model *domain.Model, sendUserId mysql.ID, giftId mysql.ID) (uint32, error) { func SumSendGift(model *domain.Model, sendUserId mysql.ID, giftId mysql.ID) (uint32, error) {
type Result struct { type Result struct {
N uint32 N uint32
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
"hilo-group/_const/enum/groupPower_e" "hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/group_power_ev" "hilo-group/domain/event/group_power_ev"
"time" "time"
) )
...@@ -40,25 +41,6 @@ type GroupPowerExpDetail struct { ...@@ -40,25 +41,6 @@ type GroupPowerExpDetail struct {
Remark string Remark string
} }
type GroupPowerOnMic struct {
Date string
GroupPowerId mysql.ID
UserId mysql.ID
Seconds int64
LastCalTs int64
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
type GroupPowerOnMicDetail struct {
Date string
GroupPowerId mysql.ID
UserId mysql.ID
Minute int
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
// 增加家族经验 // 增加家族经验
// 达到经验值之后升级 // 达到经验值之后升级
// 单进程同步执行,不考虑并发 // 单进程同步执行,不考虑并发
...@@ -152,154 +134,24 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N ...@@ -152,154 +134,24 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N
return nil return nil
} }
// 获取势力用户上麦加经验记录
func GetGroupPowerUserOnMicDetails(model *domain.Model, groupPowerId, userId mysql.ID) ([]*GroupPowerOnMicDetail, error) {
var res []*GroupPowerOnMicDetail
date := time.Now().Format("2006-01-02")
if err := model.DB().Model(GroupPowerOnMicDetail{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).Find(&res).Error; err != nil {
return res, err
}
return res, nil
}
// 获取势力用户上麦记录
func GetGroupPowerOnMic(model *domain.Model, groupPowerId, userId mysql.ID) (*GroupPowerOnMic, error) {
gpom := new(GroupPowerOnMic)
date := time.Now().Format("2006-01-02")
if err := model.DB().Model(GroupPowerOnMic{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).First(gpom).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return &GroupPowerOnMic{Date: date, GroupPowerId: groupPowerId, UserId: userId}, nil
}
return nil, err
}
return gpom, nil
}
const MaxMinuteTimes = 18
// 增加势力上麦经验 // 增加势力上麦经验
// 事务操作 // 事务操作
func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error { func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID) error {
return model.Transaction(func(model *domain.Model) error { key := mic_k.GetMicGroupPowerOnMic(userId)
// 获取用户上麦奖励历史 minutes, err := model.Redis.IncrBy(model, key, 1).Result()
onMicDetails, err := GetGroupPowerUserOnMicDetails(model, groupPowerId, userId)
if err != nil { if err != nil {
model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err)
return err return err
} }
numDetails := len(onMicDetails) model.Redis.Expire(model, key, time.Hour*24) // ttl 一天
if numDetails >= MaxMinuteTimes { // 每日最多1800经验 = 18个10分钟 = 180分钟
// 上麦经验贡献值最多1800,1分钟100 if minutes > 180 {
return nil return nil
} }
onMic, err := GetGroupPowerOnMic(model, groupPowerId, userId) if minutes%10 == 0 {
if err != nil { return IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟")
return err
}
nowTs := time.Now().Unix()
curTs := joinMicTimestamp
day0Ts := utils.GetZeroTime(time.Now()).Unix()
if joinMicTimestamp < onMic.LastCalTs {
curTs = onMic.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
onMicSeconds := nowTs - curTs
var moreDetails []*GroupPowerOnMicDetail
totalMinuteTimes := int((onMic.Seconds + onMicSeconds) / 600) // 今天实际能加经验次数
if totalMinuteTimes >= MaxMinuteTimes {
totalMinuteTimes = MaxMinuteTimes
}
if totalMinuteTimes > numDetails {
// 续上上一次的时间,从numDetails开始
for mt := numDetails + 1; mt <= totalMinuteTimes; mt++ {
moreDetails = append(moreDetails, &GroupPowerOnMicDetail{
Date: time.Now().Format("2006-01-02"),
GroupPowerId: groupPowerId,
UserId: userId,
Minute: mt * 10, // 转换分钟
})
}
}
// 有更多麦上10分钟,可以加经验
if len(moreDetails) > 0 {
for _, detail := range moreDetails {
// 添加明细,避免重复计算
if err := model.DB().Model(GroupPowerOnMicDetail{}).Create(detail).Error; err != nil {
return err
}
// 每10分钟增加100点经验
if err := IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟"); err != nil {
return err
}
}
// 更新micExp信息
onMic.Seconds = onMic.Seconds + onMicSeconds
onMic.LastCalTs = nowTs
if err := model.DB().Model(GroupPowerOnMic{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "date"}, {Name: "group_power_id"}},
DoUpdates: clause.Assignments(
map[string]interface{}{
"seconds": onMic.Seconds,
"last_cal_ts": nowTs,
},
)}).
Create(onMic).Error; err != nil {
return err
}
} }
return nil return nil
})
}
// 增加势力上麦时长-家族之星
// 事务操作
func IncrGroupPowerStarOnMicMonth(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
// 月统计
star, err := GetGroupPowerMonthStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive)
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
month0Ts := now.BeginningOfMonth().Unix()
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨月
if curTs < month0Ts {
curTs = month0Ts
}
score := nowTs - curTs
err = IncrGroupPowerMonthStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
return err
})
}
// 增加势力上麦时长-家族之星
// 事务操作
func IncrGroupPowerStarOnMicDay(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
// 日统计
star, err := GetGroupPowerDayStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive)
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
day0Ts := now.BeginningOfDay().Unix()
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
score := nowTs - curTs
err = IncrGroupPowerDayStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
return err
})
} }
// 清理所有家族的经验 // 清理所有家族的经验
......
...@@ -35,6 +35,7 @@ type GroupPowerDayStar struct { ...@@ -35,6 +35,7 @@ type GroupPowerDayStar struct {
} }
// 增加家族之星分数 // 增加家族之星分数
// Deprecated: 用redis
func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error { func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error {
month := time.Now().Format("200601") month := time.Now().Format("200601")
star := &GroupPowerMonthStar{ star := &GroupPowerMonthStar{
...@@ -59,6 +60,7 @@ func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysq ...@@ -59,6 +60,7 @@ func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysq
} }
// 增加家族之星分数 // 增加家族之星分数
// Deprecated: 用redis代替
func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error { func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error {
star := &GroupPowerDayStar{ star := &GroupPowerDayStar{
Date: time.Now(), Date: time.Now(),
...@@ -81,29 +83,8 @@ func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql. ...@@ -81,29 +83,8 @@ func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.
return nil return nil
} }
// 获取家族之星分数
// 允许返回gorm.ErrRecordNotFound
func GetGroupPowerDayStar(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType) (*GroupPowerDayStar, error) {
res := new(GroupPowerDayStar)
date := time.Now()
if err := model.DB().Where("date = ? AND group_power_id = ? AND user_id = ? AND `type` = ?", date.Format("2006-01-02"), groupPowerId, userId, _type).First(res).Error; err != nil {
return nil, err
}
return res, nil
}
// 获取家族之星分数
// 允许返回gorm.ErrRecordNotFound
func GetGroupPowerMonthStar(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType) (*GroupPowerMonthStar, error) {
res := new(GroupPowerMonthStar)
month := time.Now().Format("200601")
if err := model.DB().Where("month = ? AND group_power_id = ? AND user_id = ? AND `type` = ?", month, groupPowerId, userId, _type).First(res).Error; err != nil {
return nil, err
}
return res, nil
}
// 获取家族之星排行 // 获取家族之星排行
// Deprecated: 用redis
func GetGroupPowerMonthStarRank(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*GroupPowerMonthStar, error) { func GetGroupPowerMonthStarRank(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*GroupPowerMonthStar, error) {
var res []*GroupPowerMonthStar var res []*GroupPowerMonthStar
//month := time.Now().Format("200601") //month := time.Now().Format("200601")
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/myerr" "hilo-group/myerr"
"strconv" "strconv"
"strings" "strings"
...@@ -242,6 +243,20 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my ...@@ -242,6 +243,20 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my
if len(groupIds) <= 0 { if len(groupIds) <= 0 {
return result, nil return result, nil
} }
// 获取群组中上麦用户
for _, groupId := range groupIds {
groupMicUserKey := mic_k.GetGroupOnMicUser(groupId)
userIds, err := model.Redis.HVals(model, groupMicUserKey).Result()
if err != nil {
model.Log.Errorf("BatchGetAllMicUser fail:%v", err)
}
for _, userIdStr := range userIds {
if userId, _ := strconv.ParseUint(userIdStr, 10, 64); userId > 0 {
result[groupId] = append(result[groupId], userId)
}
}
}
return result, nil
keys := make([]string, 0) keys := make([]string, 0)
for _, g := range groupIds { for _, g := range groupIds {
...@@ -253,7 +268,7 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my ...@@ -253,7 +268,7 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my
if err != nil { if err != nil {
return nil, err return nil, err
} }
model.Log.Infof("BatchGetAllMicUser redis return size = %d, mics: %v", len(mics), mics) //model.Log.Infof("BatchGetAllMicUser redis return size = %d, mics: %v", len(mics), mics)
if len(mics) >= len(groupIds) { if len(mics) >= len(groupIds) {
for i, g := range groupIds { for i, g := range groupIds {
...@@ -432,7 +447,7 @@ func GetMicUserByExternalId(model *domain.Model, externalId string) (*MicUser, e ...@@ -432,7 +447,7 @@ func GetMicUserByExternalId(model *domain.Model, externalId string) (*MicUser, e
//麦位上没人,返回nil //麦位上没人,返回nil
func GetMicUser(model *domain.Model, groupUuid string, i int) (*MicUser, error) { func GetMicUser(model *domain.Model, groupUuid string, i int) (*MicUser, error) {
if i < 1 || i > 30 { if i < 1 || i > MaxMicNum {
return nil, myerr.NewSysErrorF("麦序不对,不在范围值内 i:%v", i) return nil, myerr.NewSysErrorF("麦序不对,不在范围值内 i:%v", i)
} }
str, err := redisCli.GetRedis().Get(context.Background(), redis_key.GetPrefixGroupMicUser(groupUuid, i)).Result() str, err := redisCli.GetRedis().Get(context.Background(), redis_key.GetPrefixGroupMicUser(groupUuid, i)).Result()
......
...@@ -31,11 +31,10 @@ var bannedGroupCache = gcache.New(100).LRU().Build() ...@@ -31,11 +31,10 @@ var bannedGroupCache = gcache.New(100).LRU().Build()
func GetBannedGroups(model *domain.Model) ([]GroupBanned, error) { func GetBannedGroups(model *domain.Model) ([]GroupBanned, error) {
key := "banned" key := "banned"
if data, err := bannedGroupCache.Get(key); err == nil { if data, err := bannedGroupCache.Get(key); err == nil {
model.Log.Infof("GetBannedGroups cache:%v", len(data.([]GroupBanned)))
return data.([]GroupBanned), nil return data.([]GroupBanned), nil
} }
result := make([]GroupBanned, 0) result := make([]GroupBanned, 0)
err := model.Db.Find(&result).Error err := model.DB().Find(&result).Error
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
package group_m
import "git.hilo.cn/hilo-common/domain"
// 获取游戏房
func GetGameGroupsMap(model *domain.Model) map[string]bool {
res := make(map[string]bool)
var rows []GroupInfo
if err := model.DB().Model(GroupInfo{}).Where("is_game_room = 1").Find(&rows).Error; err != nil {
model.Log.Errorf("GetGameGroupsMap fail:%v", err)
return res
}
for _, v := range rows {
res[v.ImGroupId] = true
}
return res
}
...@@ -47,6 +47,7 @@ type GroupInfo struct { ...@@ -47,6 +47,7 @@ type GroupInfo struct {
CreatedTime time.Time `gorm:"->"` CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"` UpdatedTime time.Time `gorm:"->"`
VisitCount int64 `gorm:"-"` // 热度 VisitCount int64 `gorm:"-"` // 热度
IsGameRoom uint8 // 是否1v1游戏房
} }
func GenerateGroupCode(n uint16) string { func GenerateGroupCode(n uint16) string {
......
...@@ -3,6 +3,7 @@ package group_m ...@@ -3,6 +3,7 @@ package group_m
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config" "git.hilo.cn/hilo-common/resource/config"
...@@ -14,6 +15,7 @@ import ( ...@@ -14,6 +15,7 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/common" "hilo-group/common"
"hilo-group/domain/model/noble_m" "hilo-group/domain/model/noble_m"
"hilo-group/domain/model/res_m" "hilo-group/domain/model/res_m"
...@@ -98,8 +100,8 @@ func GetMicNumType(model *domain.Model, groupUuid string) (group_e.GroupMicNumTy ...@@ -98,8 +100,8 @@ func GetMicNumType(model *domain.Model, groupUuid string) (group_e.GroupMicNumTy
} }
} }
//6个小时 // 3天
const expireMinute = 60 * 60 * 12 const expireMinute = 60 * 60 * 24 * 3
const micExpire = expireMinute * time.Second const micExpire = expireMinute * time.Second
//麦位基本信息。 //麦位基本信息。
...@@ -255,6 +257,10 @@ func (mic *Mic) In(userId uint64, externalId string) error { ...@@ -255,6 +257,10 @@ func (mic *Mic) In(userId uint64, externalId string) error {
return bizerr.GroupMicUserHasIn return bizerr.GroupMicUserHasIn
} }
// 增加群组中上麦用户
groupMicUserKey := mic_k.GetGroupOnMicUser(mic.GroupUuid)
mic.model.Redis.HSet(mic.model, groupMicUserKey, mic.I, userId)
//离开动作已结束,增加到队列中 //离开动作已结束,增加到队列中
MicChangeRPush(mic.model, mic.GroupUuid, mic.I) MicChangeRPush(mic.model, mic.GroupUuid, mic.I)
...@@ -385,6 +391,10 @@ func (micUser *MicUser) leave(operateUserId uint64, operateExternalId string) er ...@@ -385,6 +391,10 @@ func (micUser *MicUser) leave(operateUserId uint64, operateExternalId string) er
//return bizerr.GroupMicErr //return bizerr.GroupMicErr
} }
// 减少群组中上麦用户
groupMicUserKey := mic_k.GetGroupOnMicUser(micUser.GroupUuid)
micUser.model.Redis.HDel(micUser.model, groupMicUserKey, fmt.Sprintf("%d", micUser.I))
//离开动作已结束,增加到队列中 //离开动作已结束,增加到队列中
MicChangeRPush(micUser.model, micUser.GroupUuid, micUser.I) MicChangeRPush(micUser.model, micUser.GroupUuid, micUser.I)
...@@ -824,12 +834,14 @@ func groupMicHasIn(model *domain.Model, groupId string, userId mysql.ID) { ...@@ -824,12 +834,14 @@ func groupMicHasIn(model *domain.Model, groupId string, userId mysql.ID) {
} else { } else {
println(n) println(n)
} }
if _, err := redisCli.GetRedis().ZAdd(context.Background(), redis_key.GetPrefixGroupMicHasInUserTime(), &redis2.Z{ // 下面的是只写,不查的。 todo 直接干掉???
Score: float64(time.Now().Unix()), // 只是知道用户在哪个时间点上了哪个群的麦,但是不知道上了哪个麦位置, 而且micUser已经有统计这些信息了
Member: getMemberStr(groupId, userId), //if _, err := redisCli.GetRedis().ZAdd(context.Background(), redis_key.GetPrefixGroupMicHasInUserTime(), &redis2.Z{
}).Result(); err != nil { // Score: float64(time.Now().Unix()),
model.Log.Errorf("groupMicHasIn redis:GetPrefixGroupMicHasInTime groupId:%v err:%v", groupId, err) // Member: getMemberStr(groupId, userId),
} //}).Result(); err != nil {
// model.Log.Errorf("groupMicHasIn redis:GetPrefixGroupMicHasInTime groupId:%v err:%v", groupId, err)
//}
} }
const micHasInScript = "local flag = redis.call('EXISTS', '{key1}', '{key2}', '{key3}', '{key4}', '{key5}', '{key6}', '{key7}', '{key8}', '{key9}', '{key10}', '{key11}', '{key12}', '{key13}', '{key14}', '{key15}', '{key16}', '{key17}', '{key18}', '{key19}', '{key20}') if flag == 0 then redis.call('Srem', '{key}', '{remKey}') end return flag " const micHasInScript = "local flag = redis.call('EXISTS', '{key1}', '{key2}', '{key3}', '{key4}', '{key5}', '{key6}', '{key7}', '{key8}', '{key9}', '{key10}', '{key11}', '{key12}', '{key13}', '{key14}', '{key15}', '{key16}', '{key17}', '{key18}', '{key19}', '{key20}') if flag == 0 then redis.call('Srem', '{key}', '{remKey}') end return flag "
...@@ -843,6 +855,7 @@ func GetMicHasInGroups() ([]string, error) { ...@@ -843,6 +855,7 @@ func GetMicHasInGroups() ([]string, error) {
if err != nil { if err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
return groupUuids, nil // 不需要下面的逐个麦位的判断了
// //
resultGroupUuids := make([]string, 0, len(groupUuids)) resultGroupUuids := make([]string, 0, len(groupUuids))
//循环lua判断是否, 最后的保证,(猜想:真正麦上有人的群没有很多) //循环lua判断是否, 最后的保证,(猜想:真正麦上有人的群没有很多)
...@@ -875,7 +888,7 @@ var micGroupNumCache = gcache.New(10000).LRU().Build() ...@@ -875,7 +888,7 @@ var micGroupNumCache = gcache.New(10000).LRU().Build()
func GetMicHasInGroupNum(model *domain.Model) (map[string]int64, error) { func GetMicHasInGroupNum(model *domain.Model) (map[string]int64, error) {
// get from cache // get from cache
if data, err := micGroupNumCache.Get(micGroupNumKey); err == nil { if data, err := micGroupNumCache.Get(micGroupNumKey); err == nil {
model.Log.Infof("GetMicHasInGroupNum cache hit:%v", data) //model.Log.Infof("GetMicHasInGroupNum cache hit:%v", data)
// 正服才缓存 // 正服才缓存
if config.AppIsRelease() { if config.AppIsRelease() {
return data.(map[string]int64), nil return data.(map[string]int64), nil
...@@ -912,8 +925,41 @@ func GetMicHasInGroupNum(model *domain.Model) (map[string]int64, error) { ...@@ -912,8 +925,41 @@ func GetMicHasInGroupNum(model *domain.Model) (map[string]int64, error) {
} }
} }
// cache 1min // cache 1min
_ = micGroupNumCache.SetWithExpire(micGroupNumKey, resultGroupUuids, time.Minute) _ = micGroupNumCache.SetWithExpire(micGroupNumKey, resultGroupUuids, time.Minute*15)
model.Log.Infof("GetMicHasInGroupNum cache miss:%v", resultGroupUuids) return resultGroupUuids, nil
}
// 获取麦上人数
func GetMicHasInGroupNumByList(model *domain.Model, groupIds []string) (map[string]int64, error) {
resultGroupUuids := make(map[string]int64, len(groupIds))
micHasInKey := redis_key.GetPrefixGroupMicHasIn()
for _, group := range groupIds {
isMem, err := redisCli.GetRedis().SIsMember(context.Background(), micHasInKey, group).Result()
if err != nil {
model.Log.Errorf("GetMicHasInGroupNumByList err:%v", err)
return nil, myerr.WrapErr(err)
}
if isMem {
s := strings.Replace(micHasInScript, "{key}", micHasInKey, -1)
s = strings.Replace(s, "{remKey}", group, -1)
for i := 1; i <= MaxMicNum; i++ {
s = strings.Replace(s, "{key"+strconv.Itoa(i)+"}", redis_key.GetPrefixGroupMicUser(group, i), -1)
}
//r, err := redis2.NewScript(s).Run(context.Background(), redisCli.GetRedis(), []string{}).Result()
sha1, err := model.Redis.ScriptLoad(model, s).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
micNum, err := model.Redis.EvalSha(model, sha1, nil, nil).Int64()
if err != nil {
return nil, myerr.WrapErr(err)
}
//d := r.(int64)
if micNum > 0 {
resultGroupUuids[group] = micNum
}
}
}
return resultGroupUuids, nil return resultGroupUuids, nil
} }
......
...@@ -68,7 +68,7 @@ type MicNumChangeContent struct { ...@@ -68,7 +68,7 @@ type MicNumChangeContent struct {
Timestamp int64 `json:"timestamp"` Timestamp int64 `json:"timestamp"`
} }
func MicGroupKickOutRPush(model *domain.Model, groupUid string, userExternalId string, beKickExternalId string) { func MicGroupKickOutRPush(model *domain.Model, groupUid string, userExternalId string, beKickExternalId string, beKickuserId uint64) {
model.Log.Infof("MicChangeRPush MicGroupKickOutRPush begin groupUuid:%v", groupUid) model.Log.Infof("MicChangeRPush MicGroupKickOutRPush begin groupUuid:%v", groupUid)
txGroupId, err := ToTxGroupId(model, groupUid) txGroupId, err := ToTxGroupId(model, groupUid)
...@@ -94,7 +94,9 @@ func MicGroupKickOutRPush(model *domain.Model, groupUid string, userExternalId s ...@@ -94,7 +94,9 @@ func MicGroupKickOutRPush(model *domain.Model, groupUid string, userExternalId s
model.Log.Errorf("MicChangeRPush MicGroupKickOutRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str)) model.Log.Errorf("MicChangeRPush MicGroupKickOutRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str))
return return
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { // socket通知被拉黑者退房
rpc.SendQuitRoom(beKickuserId, 2, txGroupId)
if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicChangeRPush MicGroupKickOutRPush err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str)) model.Log.Errorf("MicChangeRPush MicGroupKickOutRPush err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str))
return return
} else { } else {
...@@ -128,7 +130,7 @@ func MicSocketMicOutRPush(model *domain.Model, groupUid string, userExternalId s ...@@ -128,7 +130,7 @@ func MicSocketMicOutRPush(model *domain.Model, groupUid string, userExternalId s
model.Log.Errorf("MicChangeRPush MicSocketMicOutRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str)) model.Log.Errorf("MicChangeRPush MicSocketMicOutRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str))
return return
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicChangeRPush MicSocketMicOutRPush err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str)) model.Log.Errorf("MicChangeRPush MicSocketMicOutRPush err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str))
return return
} else { } else {
...@@ -163,7 +165,7 @@ func MicNumChangeRPush(model *domain.Model, groupUid string, micNumType group_e. ...@@ -163,7 +165,7 @@ func MicNumChangeRPush(model *domain.Model, groupUid string, micNumType group_e.
model.Log.Errorf("MicChangeRPush MicNumChangeRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str)) model.Log.Errorf("MicChangeRPush MicNumChangeRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str))
return return
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicChangeRPush MicNumChangeRPush err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str)) model.Log.Errorf("MicChangeRPush MicNumChangeRPush err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str))
return return
} else { } else {
...@@ -204,7 +206,7 @@ func MicEmptyRPush(model *domain.Model, groupUid string, i int) { ...@@ -204,7 +206,7 @@ func MicEmptyRPush(model *domain.Model, groupUid string, i int) {
model.Log.Errorf("MicChangeRPush MicEmptyRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContent)) model.Log.Errorf("MicChangeRPush MicEmptyRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContent))
return return
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicChangeRPush MicEmptyRPush err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContent)) model.Log.Errorf("MicChangeRPush MicEmptyRPush err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContent))
return return
} else { } else {
...@@ -241,7 +243,7 @@ func MicChangeRPush(model *domain.Model, groupUid string, i int) { ...@@ -241,7 +243,7 @@ func MicChangeRPush(model *domain.Model, groupUid string, i int) {
model.Log.Errorf("MicChangeRPush MicChangeRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContentStr)) model.Log.Errorf("MicChangeRPush MicChangeRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContentStr))
return return
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicChangeRPush MicChangeRPush err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContentStr)) model.Log.Errorf("MicChangeRPush MicChangeRPush err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContentStr))
return return
} else { } else {
...@@ -259,9 +261,9 @@ func MicAllRPush(model *domain.Model, groupUid string, externalId string) error ...@@ -259,9 +261,9 @@ func MicAllRPush(model *domain.Model, groupUid string, externalId string) error
} }
// //
micContents, err := getMicAllContent(model, groupUid) micContents, err := GetMicAllContent(model, groupUid)
if err != nil { if err != nil {
model.Log.Errorf("MicChangeRPush MicAllRPush getMicAllContent err:%+v, micContents:%v groupUuid:%v, externalId:%v", err, micContents, groupUid, externalId) model.Log.Errorf("MicChangeRPush MicAllRPush GetMicAllContent err:%+v, micContents:%v groupUuid:%v, externalId:%v", err, micContents, groupUid, externalId)
return err return err
} }
for _, micContent := range micContents { for _, micContent := range micContents {
...@@ -286,7 +288,7 @@ func MicAllRPush(model *domain.Model, groupUid string, externalId string) error ...@@ -286,7 +288,7 @@ func MicAllRPush(model *domain.Model, groupUid string, externalId string) error
model.Log.Errorf("MicChangeRPush MicAllRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, externalId:%v, micContent:%+v", err, groupUid, externalId, string(micContentStr)) model.Log.Errorf("MicChangeRPush MicAllRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, externalId:%v, micContent:%+v", err, groupUid, externalId, string(micContentStr))
continue continue
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicChangeRPush MicAllRPush err:%+v, groupUuid:%v, externalId:%v, micContent:%+v", err, groupUid, externalId, string(micContentStr)) model.Log.Errorf("MicChangeRPush MicAllRPush err:%+v, groupUuid:%v, externalId:%v, micContent:%+v", err, groupUid, externalId, string(micContentStr))
continue continue
} else { } else {
...@@ -310,7 +312,7 @@ func MicRPush(model *domain.Model, txGroupId string, msg GroupSystemMsg) error { ...@@ -310,7 +312,7 @@ func MicRPush(model *domain.Model, txGroupId string, msg GroupSystemMsg) error {
model.Log.Errorf("MicRPush Marshal MicSystemMsg err:%+v, txGroupId:%v, micContent:%+v", err, txGroupId, string(str)) model.Log.Errorf("MicRPush Marshal MicSystemMsg err:%+v, txGroupId:%v, micContent:%+v", err, txGroupId, string(str))
return err return err
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicRPush err:%+v, txGroupId:%v, micContent:%+v", err, txGroupId, string(str)) model.Log.Errorf("MicRPush err:%+v, txGroupId:%v, micContent:%+v", err, txGroupId, string(str))
return err return err
} }
...@@ -319,7 +321,7 @@ func MicRPush(model *domain.Model, txGroupId string, msg GroupSystemMsg) error { ...@@ -319,7 +321,7 @@ func MicRPush(model *domain.Model, txGroupId string, msg GroupSystemMsg) error {
} }
//得使用旧的imGroupId //得使用旧的imGroupId
func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error) { func GetMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error) {
txGroupId, err := ToTxGroupId(model, groupUid) txGroupId, err := ToTxGroupId(model, groupUid)
if err != nil { if err != nil {
...@@ -340,6 +342,9 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error ...@@ -340,6 +342,9 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error
userIds := make([]uint64, 0, len(micUsers)) userIds := make([]uint64, 0, len(micUsers))
for _, r := range micUsers { for _, r := range micUsers {
userIds = append(userIds, r.UserId) userIds = append(userIds, r.UserId)
if r.CpUserId > 0 {
userIds = append(userIds, r.CpUserId)
}
} }
model.Log.Infof("MicChangeRPush getMicAllContent groupUid:%v, userIds:%+v", groupUid, userIds) model.Log.Infof("MicChangeRPush getMicAllContent groupUid:%v, userIds:%+v", groupUid, userIds)
...@@ -350,6 +355,13 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error ...@@ -350,6 +355,13 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error
micContents := make([]MicContent, 0, len(mics)) micContents := make([]MicContent, 0, len(mics))
for _, r := range mics { for _, r := range mics {
var micEffect string
cpUserId := micUserMap[r.I].CpUserId
micUserData := micUserDataMap[micUserMap[r.I].UserId]
if cpUserId > 0 {
micEffect = "https://image.whoisamy.shop/hilo/resource/svga/mic_effect_cp.svga"
micUserData.MicEffect = micEffect
}
micContents = append(micContents, MicContent{ micContents = append(micContents, MicContent{
GroupId: txGroupId, GroupId: txGroupId,
I: r.I, I: r.I,
...@@ -359,7 +371,7 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error ...@@ -359,7 +371,7 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error
ExternalId: micUserMap[r.I].ExternalId, ExternalId: micUserMap[r.I].ExternalId,
AgoraId: uint32(micUserMap[r.I].UserId), AgoraId: uint32(micUserMap[r.I].UserId),
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().UnixNano(),
User: micUserDataMap[micUserMap[r.I].UserId], User: micUserData,
}) })
} }
return micContents, nil return micContents, nil
...@@ -448,6 +460,7 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser ...@@ -448,6 +460,7 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser
return nil, err return nil, err
} }
svips, _ := rpc.MGetUserSvip(model, userIds) svips, _ := rpc.MGetUserSvip(model, userIds)
cpRelations, _ := rpc.MGetUserCpRelations(model, userIds)
micUserDataMap := map[uint64]*MicUserData{} micUserDataMap := map[uint64]*MicUserData{}
for _, id := range userIds { for _, id := range userIds {
...@@ -461,11 +474,11 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser ...@@ -461,11 +474,11 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser
} }
var headwearPicUrl string var headwearPicUrl string
var headwearEffectUrl string var headwearEffectUrl string
var reverseHeadwearEffectUrl string var headwearReverseEffectUrl string
if headwearUser, flag := headwearMap[id]; flag { if headwearUser, flag := headwearMap[id]; flag {
headwearPicUrl = resHeadwearMap[headwearUser.HeadwearId].PicUrl headwearPicUrl = resHeadwearMap[headwearUser.HeadwearId].PicUrl
headwearEffectUrl = resHeadwearMap[headwearUser.HeadwearId].EffectUrl headwearEffectUrl = resHeadwearMap[headwearUser.HeadwearId].EffectUrl
reverseHeadwearEffectUrl = resHeadwearMap[headwearUser.HeadwearId].ReverseEffectUrl headwearReverseEffectUrl = resHeadwearMap[headwearUser.HeadwearId].ReverseEffectUrl
} }
micUserDataMap[id] = &MicUserData{ micUserDataMap[id] = &MicUserData{
Id: user.ID, Id: user.ID,
...@@ -478,9 +491,10 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser ...@@ -478,9 +491,10 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser
NobleLeave: nobleMap[id], NobleLeave: nobleMap[id],
HeadwearPicUrl: headwearPicUrl, HeadwearPicUrl: headwearPicUrl,
HeadwearEffectUrl: headwearEffectUrl, HeadwearEffectUrl: headwearEffectUrl,
HeadwearReverseEffectUrl: reverseHeadwearEffectUrl, HeadwearReverseEffectUrl: headwearReverseEffectUrl,
SvipLevel: svips[id].SvipLevel, SvipLevel: svips[id].SvipLevel,
Svip: rpc.CopySimpleSvip(svips[id]), Svip: rpc.CopySimpleSvip(svips[id]),
HeadwearIcon: cpRelations[user.ID].CpUserAvatar,
} }
} }
return micUserDataMap, nil return micUserDataMap, nil
......
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/group_k"
"hilo-group/domain/cache/room_c" "hilo-group/domain/cache/room_c"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/myerr" "hilo-group/myerr"
...@@ -49,14 +50,14 @@ func RoomLivingExpire(model *domain.Model, groupUid string, userId uint64) { ...@@ -49,14 +50,14 @@ func RoomLivingExpire(model *domain.Model, groupUid string, userId uint64) {
model.Log.Infof("room RoomLivingExpire userId:%v, groupUid:%v", userId, groupUid) model.Log.Infof("room RoomLivingExpire userId:%v, groupUid:%v", userId, groupUid)
// //
key := redis_key.GetPrefixGroupRoomLiving() key := redis_key.GetPrefixGroupRoomLiving()
i, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{ _, err := model.RedisCluster.ZAdd(context.Background(), key, &redis2.Z{
Score: float64(time.Now().Unix()), Score: float64(time.Now().Unix()),
Member: getMemberStr(groupUid, userId), Member: getMemberStr(groupUid, userId),
}).Result() }).Result()
if err != nil { if err != nil {
model.Log.Errorf("RoomLivingExpire ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err) model.Log.Errorf("RoomLivingExpire ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err)
} else { } else {
model.Log.Infof("RoomLivingExpire ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i) //model.Log.Infof("RoomLivingExpire ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i)
} }
} }
...@@ -69,14 +70,14 @@ func RoomLivingIn(model *domain.Model, groupUid string, userId uint64, externalI ...@@ -69,14 +70,14 @@ func RoomLivingIn(model *domain.Model, groupUid string, userId uint64, externalI
} }
// //
key := redis_key.GetPrefixGroupRoomLiving() key := redis_key.GetPrefixGroupRoomLiving()
i, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{ _, err := model.RedisCluster.ZAdd(context.Background(), key, &redis2.Z{
Score: float64(time.Now().Unix()), Score: float64(time.Now().Unix()),
Member: getMemberStr(groupUid, userId), Member: getMemberStr(groupUid, userId),
}).Result() }).Result()
if err != nil { if err != nil {
model.Log.Errorf("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err) model.Log.Errorf("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err)
} else { } else {
model.Log.Infof("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i) //model.Log.Infof("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i)
} }
go func(myContext *mycontext.MyContext, groupId string) { go func(myContext *mycontext.MyContext, groupId string) {
...@@ -111,11 +112,11 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri ...@@ -111,11 +112,11 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri
key := redis_key.GetPrefixGroupRoomLiving() key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil { //if err := redisCli.ClearExpired(key, expireMinute); err != nil {
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil { if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
data, err := redisCli.GetRedis().ZRange(context.Background(), key, 0, -1).Result() data, err := model.RedisCluster.ZRange(context.Background(), key, 0, -1).Result()
if err != nil { if err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
...@@ -124,12 +125,12 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri ...@@ -124,12 +125,12 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri
for i, _ := range data { for i, _ := range data {
gid, uid := analysisMemberStr(data[i]) gid, uid := analysisMemberStr(data[i])
if uid == userId && (groupId == "" || gid == groupId) { if uid == userId && (groupId == "" || gid == groupId) {
if _, err := redisCli.GetRedis().ZRem(context.Background(), key, getMemberStr(gid, uid)).Result(); err != nil { if _, err := model.RedisCluster.ZRem(context.Background(), key, getMemberStr(gid, uid)).Result(); err != nil {
model.Log.Errorf("RoomLivingLeave ZRem key:%s, groupId:%s, userId:%d, err:%v", key, gid, uid, err) model.Log.Errorf("RoomLivingLeave ZRem key:%s, groupId:%s, userId:%d, err:%v", key, gid, uid, err)
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} else { } else {
groupIds = append(groupIds, gid) groupIds = append(groupIds, gid)
model.Log.Infof("RoomLivingLeave ZRem success key:%s, groupId:%s, userId:%d", key, gid, uid) //model.Log.Infof("RoomLivingLeave ZRem success key:%s, groupId:%s, userId:%d", key, gid, uid)
} }
// 发信令,让前端重新拉取,接受容错, // 发信令,让前端重新拉取,接受容错,
...@@ -208,7 +209,7 @@ func RoomLivingLeaveByKick(model *domain.Model, groupUuid string, beKickuserId u ...@@ -208,7 +209,7 @@ func RoomLivingLeaveByKick(model *domain.Model, groupUuid string, beKickuserId u
Target: beKickExternalId, Target: beKickExternalId,
}, false)*/ }, false)*/
MicGroupKickOutRPush(model, groupUuid, userExternalId, beKickExternalId) MicGroupKickOutRPush(model, groupUuid, userExternalId, beKickExternalId, beKickuserId)
return roomLivingLeave(model, beKickuserId, groupUuid) return roomLivingLeave(model, beKickuserId, groupUuid)
} }
...@@ -271,15 +272,15 @@ func RoomLivingExistsUserId(groupUid string) ([]uint64, error) { ...@@ -271,15 +272,15 @@ func RoomLivingExistsUserId(groupUid string) ([]uint64, error) {
key := redis_key.GetPrefixGroupRoomLiving() key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil { //if err := redisCli.ClearExpired(key, expireMinute); err != nil {
var model = domain.CreateModelNil() var model = domain.CreateModelNil()
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil { if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
groupUserIdstrs, err := redisCli.GetRedis().ZRevRange(context.Background(), key, 0, -1).Result() groupUserIdstrs, err := model.RedisCluster.ZRevRange(context.Background(), key, 0, -1).Result()
if err != nil { if err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
mylogrus.MyLog.Infof("group_room_living RoomLivingExistsUserId groupUserIdstrs:%v", groupUserIdstrs) //mylogrus.MyLog.Infof("group_room_living RoomLivingExistsUserId groupUserIdstrs:%v", groupUserIdstrs)
userIds := make([]uint64, 0, len(groupUserIdstrs)) userIds := make([]uint64, 0, len(groupUserIdstrs))
for i, _ := range groupUserIdstrs { for i, _ := range groupUserIdstrs {
tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i]) tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i])
...@@ -299,11 +300,11 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) { ...@@ -299,11 +300,11 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) {
key := redis_key.GetPrefixGroupRoomLiving() key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil { //if err := redisCli.ClearExpired(key, expireMinute); err != nil {
model := domain.CreateModelNil() model := domain.CreateModelNil()
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil { if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
groupUserIdstrs, err := redisCli.GetRedis().ZRange(context.Background(), key, 0, -1).Result() groupUserIdstrs, err := model.RedisCluster.ZRange(context.Background(), key, 0, -1).Result()
if err != nil { if err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
...@@ -324,16 +325,16 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) { ...@@ -324,16 +325,16 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) {
func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{}, error) { func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{}, error) {
key := redis_key.GetPrefixGroupRoomLiving() key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil { //if err := redisCli.ClearExpired(key, expireMinute); err != nil {
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil { if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
model.Log.Infof("RoomLivingExistsGroup: err:%v", err) model.Log.Infof("RoomLivingExistsGroup: err:%v", err)
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
groupUserIdstrs, err := redisCli.GetRedis().ZRange(context.Background(), key, 0, -1).Result() groupUserIdstrs, err := model.RedisCluster.ZRange(context.Background(), key, 0, -1).Result()
if err != nil { if err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
model.Log.Infof("group_room_living RoomLivingExistsGroup groupUserIdstrs:%v", groupUserIdstrs) //model.Log.Infof("group_room_living RoomLivingExistsGroup groupUserIdstrs:%v", groupUserIdstrs)
groupGroup := map[string]map[uint64]struct{}{} groupGroup := map[string]map[uint64]struct{}{}
for i, _ := range groupUserIdstrs { for i, _ := range groupUserIdstrs {
tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i]) tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i])
...@@ -343,7 +344,7 @@ func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{}, ...@@ -343,7 +344,7 @@ func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{},
groupGroup[tempGroupUid] = map[uint64]struct{}{userId: {}} groupGroup[tempGroupUid] = map[uint64]struct{}{userId: {}}
} }
} }
model.Log.Infof("RoomLivingExistsGroup size = %d", len(groupGroup)) //model.Log.Infof("RoomLivingExistsGroup size = %d", len(groupGroup))
return groupGroup, nil return groupGroup, nil
} }
...@@ -389,18 +390,8 @@ func GetAllGroupsSorted(model *domain.Model) ([]string, error) { ...@@ -389,18 +390,8 @@ func GetAllGroupsSorted(model *domain.Model) ([]string, error) {
// 取房间最近N天的访问人数 // 取房间最近N天的访问人数
func GetRoomVisitCount(groupId string) (int64, error) { func GetRoomVisitCount(groupId string) (int64, error) {
// 每群定时请一次数据可以了 key := group_k.GetUserEnterRoomGroupKey(groupId)
now := time.Now() visitCount, err := redisCli.GetRedis().ZCard(context.Background(), key).Result()
if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
// 先移除(N天之前的),后统计
if _, err := redisCli.GetRedis().ZRemRangeByScore(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId),
"0", strconv.FormatInt(time.Now().AddDate(0, 0, -redis_key.GroupInDurationTTL).Unix(), 10)).
Result(); err != nil {
return 0, err
}
}
visitCount, err := redisCli.GetRedis().ZCard(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId)).Result()
if err != nil { if err != nil {
return 0, err return 0, err
} }
...@@ -429,15 +420,12 @@ func BatchGetRoomVisitCount(logE *logrus.Entry, groupIds []string) (map[string]i ...@@ -429,15 +420,12 @@ func BatchGetRoomVisitCount(logE *logrus.Entry, groupIds []string) (map[string]i
if err != nil { if err != nil {
return nil, err return nil, err
} }
logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
visitCount := make(map[string]int64) visitCount := make(map[string]int64)
for _, groupId := range groupIds { for _, groupId := range groupIds {
// 先从二级缓存中找 // 先从二级缓存中找
if c, ok := roomVisitCount[groupId]; ok { if c, ok := roomVisitCount[groupId]; ok {
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 { if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
logE.Debugf("GetRoomVisitCount, from roomVisitCount %s - %d", groupId, vc)
visitCount[groupId] = vc visitCount[groupId] = vc
} }
} else { } else {
...@@ -464,7 +452,7 @@ func BatchGetRoomVisitCountList(logE *logrus.Entry, groupIds []string) (map[stri ...@@ -464,7 +452,7 @@ func BatchGetRoomVisitCountList(logE *logrus.Entry, groupIds []string) (map[stri
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
logE.Infof("MGetRoomVisitCount:%v", roomVisitCount) //logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
res := make([]*RoomVisit, 0, len(groupIds)) res := make([]*RoomVisit, 0, len(groupIds))
visitCount := make(map[string]int64) visitCount := make(map[string]int64)
......
...@@ -57,6 +57,24 @@ func GetAllGroupSupportResult(db *gorm.DB, period string) (map[string]uint8, err ...@@ -57,6 +57,24 @@ func GetAllGroupSupportResult(db *gorm.DB, period string) (map[string]uint8, err
return result, nil return result, nil
} }
func GetGroupSupportResult(db *gorm.DB, period string, groupIds []string) (map[string]uint8, error) {
if len(period) <= 0 {
return nil, nil
}
gsr := GroupSupportResult{
Period: period,
}
rows := make([]GroupSupportResult, 0)
if err := db.Where(gsr).Where("group_uid in (?)", groupIds).Find(&rows).Error; err != nil {
return nil, err
}
result := make(map[string]uint8)
for _, i := range rows {
result[i.GroupUid] = i.Grade
}
return result, nil
}
//群组扶持奖励,利益分配者 //群组扶持奖励,利益分配者
type GroupSupportAwardAdmin struct { type GroupSupportAwardAdmin struct {
mysql.Entity mysql.Entity
...@@ -102,14 +120,14 @@ func (gsa *GroupSupportAwardMgr) Get(db *gorm.DB) ([]GroupSupportAwardMgr, error ...@@ -102,14 +120,14 @@ func (gsa *GroupSupportAwardMgr) Get(db *gorm.DB) ([]GroupSupportAwardMgr, error
} }
//添加记录 //添加记录
func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mysql.ID, resGroupSupportId mysql.ID, userIds []mysql.ID, period string) (*GroupSupportAwardAdmin, []GroupSupportAwardMgr, error) { func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mysql.ID, resSupport *res_m.ResGroupSupport, userIds []mysql.ID, period string) (*GroupSupportAwardAdmin, []GroupSupportAwardMgr, error) {
//资源获取 ////资源获取
resGroupSupport, err := res_m.GetResGroupSupportById(model, resGroupSupportId) //resGroupSupport, err := res_m.GetResGroupSupportById(model, resGroupSupportId)
if err != nil { //if err != nil {
return nil, nil, err // return nil, nil, err
} //}
if int(resGroupSupport.MgrNum) < len(userIds) { if int(resSupport.MgrNum) < len(userIds) {
return nil, nil, myerr.NewSysErrorF("AddGroupSupportAward mgrNum:%v 同 len(userIds)=%v 不一致", resGroupSupport.MgrNum, len(userIds)) return nil, nil, myerr.NewSysErrorF("AddGroupSupportAward mgrNum:%v 同 len(userIds)=%v 不一致", resSupport.MgrNum, len(userIds))
} }
//增加群主奖励 //增加群主奖励
...@@ -118,9 +136,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys ...@@ -118,9 +136,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys
GroupUid: groupUid, GroupUid: groupUid,
IssuerUserId: issuerUserId, IssuerUserId: issuerUserId,
UserId: issuerUserId, UserId: issuerUserId,
DiamondNum: resGroupSupport.AdminAward, DiamondNum: resSupport.AdminAward,
Grade: resGroupSupport.Grade, Grade: resSupport.Grade,
ResGroupSupportId: resGroupSupport.ID, ResGroupSupportId: resSupport.ID,
Period: period, Period: period,
} }
...@@ -133,9 +151,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys ...@@ -133,9 +151,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys
GroupUid: groupUid, GroupUid: groupUid,
IssuerUserId: issuerUserId, IssuerUserId: issuerUserId,
UserId: userIds[i], UserId: userIds[i],
DiamondNum: resGroupSupport.MgrAward, DiamondNum: resSupport.MgrAward,
Grade: resGroupSupport.Grade, Grade: resSupport.Grade,
ResGroupSupportId: resGroupSupport.ID, ResGroupSupportId: resSupport.ID,
Period: period, Period: period,
}) })
} }
......
...@@ -104,7 +104,8 @@ func (rb *RoomBanner) GetRoomBanners(db *gorm.DB, vcAllow bool) ([]RoomBanner, e ...@@ -104,7 +104,8 @@ func (rb *RoomBanner) GetRoomBanners(db *gorm.DB, vcAllow bool) ([]RoomBanner, e
res := make([]RoomBanner, 0, len(rows)) res := make([]RoomBanner, 0, len(rows))
for _, v := range rows { for _, v := range rows {
// 版本控制 // 版本控制
if !vcAllow && (v.ID == 241 || v.ID == 781 || v.ID == 771 || v.ID == 911 || v.ID == 841 || v.ID == 851 || v.ID == 1001 || v.ID == 981) { if !vcAllow && (v.ID == 241 || v.ID == 781 || v.ID == 771 || v.ID == 911 || v.ID == 841 ||
v.ID == 851 || v.ID == 1001 || v.ID == 981 || v.ID == 1451 || v.ID == 1621) {
continue continue
} }
res = append(res, v) res = append(res, v)
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"git.hilo.cn/hilo-common/utils" "git.hilo.cn/hilo-common/utils"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
"hilo-group/_const/redis_key/mic_k"
"time" "time"
) )
...@@ -75,6 +76,45 @@ func IncrUserOnMic(model *domain.Model, userId mysql.ID, joinMicTimestamp int64) ...@@ -75,6 +76,45 @@ func IncrUserOnMic(model *domain.Model, userId mysql.ID, joinMicTimestamp int64)
}) })
} }
// 增加用户上麦时长
// 事务操作
func IncrUserOnMicV2(model *domain.Model, userId mysql.ID) error {
for _, tz := range timezone_e.Timezones {
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
if err := model.DB().Model(UserOnMic{}).Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}, {Name: "tz"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"seconds": gorm.Expr("seconds + ?", 60),
}),
}).Create(&UserOnMic{
Date: day,
UserId: userId,
Seconds: 60,
Tz: tz,
}).Error; err != nil {
model.Log.Errorf("IncrUserOnMic fail:%v", err)
return err
}
}
return nil
}
// 增加用户上麦时长
// Redis
func IncrUserOnMicV3(model *domain.Model, userId mysql.ID) error {
for _, tz := range timezone_e.Timezones {
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
tzStr := "bj"
if tz == timezone_e.TimezoneKSA {
tzStr = "ksa"
}
tzKey := mic_k.GetUserOnMicKey(userId, tzStr, day)
model.RedisCluster.IncrBy(model, tzKey, 60)
model.RedisCluster.Expire(model, tzKey, time.Hour*24*30) // 30天上麦时长
}
return nil
}
// 批量获取用户上麦时长 // 批量获取用户上麦时长
// @return userId->seconds // @return userId->seconds
func MGetUserOnMicSeconds(model *domain.Model, day string, tz timezone_e.Timezone, userIds []uint64) (map[mysql.ID]mysql.Num, error) { func MGetUserOnMicSeconds(model *domain.Model, day string, tz timezone_e.Timezone, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
......
...@@ -144,7 +144,7 @@ func BatchGetActiveNoble(db *gorm.DB, userIds []uint64) (map[uint64]UserNoble, e ...@@ -144,7 +144,7 @@ func BatchGetActiveNoble(db *gorm.DB, userIds []uint64) (map[uint64]UserNoble, e
start += NUM start += NUM
end += NUM end += NUM
} }
mylogrus.MyLog.Infof("BatchGetActiveNoble expected:%v,actual:%v,notEndUids:%v", len(userIds), len(result), notEndUids) //mylogrus.MyLog.Infof("BatchGetActiveNoble expected:%v,actual:%v,notEndUids:%v", len(userIds), len(result), notEndUids)
if len(userIds) != len(result) { if len(userIds) != len(result) {
mylogrus.MyLog.Warnf("BatchGetActiveNoble expected:%v", userIds) mylogrus.MyLog.Warnf("BatchGetActiveNoble expected:%v", userIds)
} }
......
...@@ -213,3 +213,10 @@ func GetLangeByCountry(db *gorm.DB, country mysql.Str) (string, error) { ...@@ -213,3 +213,10 @@ func GetLangeByCountry(db *gorm.DB, country mysql.Str) (string, error) {
return "", myerr.WrapErr(err) return "", myerr.WrapErr(err)
} }
} }
//获取所有国家名字列表
func GetCountryNameList(model *domain.Model) ([]string, error) {
res := make([]string, 0)
err := model.DB().Table("res_country").Select("distinct(name) name").Pluck("name", &res).Error
return res, myerr.WrapErr(err)
}
...@@ -325,7 +325,7 @@ func GetOnlineStatus(model *domain.Model, extIds []string) (map[string]uint, err ...@@ -325,7 +325,7 @@ func GetOnlineStatus(model *domain.Model, extIds []string) (map[string]uint, err
model.Log.Warnf("getOnlineStatus redis failed") model.Log.Warnf("getOnlineStatus redis failed")
left = extIds left = extIds
} else { } else {
model.Log.Infof("getOnlineStatus redis return size = %d: %v", len(r), r) //model.Log.Infof("getOnlineStatus redis return size = %d: %v", len(r), r)
if len(r) >= len(extIds) { if len(r) >= len(extIds) {
for i, e := range extIds { for i, e := range extIds {
...@@ -387,10 +387,10 @@ func getOnlineStatus(extIds []string) ([]interface{}, error) { ...@@ -387,10 +387,10 @@ func getOnlineStatus(extIds []string) ([]interface{}, error) {
for _, e := range extIds { for _, e := range extIds {
keys = append(keys, redis_key.GetOnLineStatusKey(e)) keys = append(keys, redis_key.GetOnLineStatusKey(e))
} }
return redisCli.RedisClient.MGet(context.Background(), keys...).Result() return redisCli.RedisClusterClient.MGet(context.Background(), keys...).Result()
} }
func setOnlineStatus(extId string, status uint, ttl time.Duration) error { func setOnlineStatus(extId string, status uint, ttl time.Duration) error {
key := redis_key.GetOnLineStatusKey(extId) key := redis_key.GetOnLineStatusKey(extId)
return redisCli.RedisClient.Set(context.Background(), key, status, ttl).Err() return redisCli.RedisClusterClient.Set(context.Background(), key, status, ttl).Err()
} }
...@@ -48,8 +48,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui ...@@ -48,8 +48,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
if err != nil { if err != nil {
return nil, err return nil, err
} }
logger.Infof("GetUserMedalLevelMap, user %d, medalMap %+v", medalTypes) //logger.Infof("GetUserMedalLevelMap, user %d, medalMap %+v", medalTypes)
logger.Infof("GetUserMedalLevelMap, user %d, medalList %+v", medalList) //logger.Infof("GetUserMedalLevelMap, user %d, medalList %+v", medalList)
maxGrades := make(map[uint8]int, 0) maxGrades := make(map[uint8]int, 0)
maxMedalIds := make(map[uint8]uint32, 0) maxMedalIds := make(map[uint8]uint32, 0)
...@@ -70,8 +70,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui ...@@ -70,8 +70,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
} }
} }
} }
logger.Infof("maxGrade %+v", maxGrades) //logger.Infof("maxGrade %+v", maxGrades)
logger.Infof("maxMedalIds %+v", maxMedalIds) //logger.Infof("maxMedalIds %+v", maxMedalIds)
mIds := result mIds := result
result = make([]uint32, 0) result = make([]uint32, 0)
......
...@@ -94,10 +94,7 @@ func GetUserMapByIds(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]User ...@@ -94,10 +94,7 @@ func GetUserMapByIds(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]User
} }
var rows []User var rows []User
start := 0 start := 0
for end <= len(userIds) { for start < len(userIds) {
if end > len(userIds) {
end = len(userIds)
}
tmp, err := GetUsersByIds(model, userIds[start:end]) tmp, err := GetUsersByIds(model, userIds[start:end])
if err != nil { if err != nil {
return result, err return result, err
...@@ -106,7 +103,10 @@ func GetUserMapByIds(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]User ...@@ -106,7 +103,10 @@ func GetUserMapByIds(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]User
} }
start += 500 start += 500
end += 500 end += 500
model.Log.Infof("GetUserMapByIds start:%v-end:%v", start, end) if end > len(userIds) {
end = len(userIds)
}
//model.Log.Infof("GetUserMapByIds start:%v-end:%v", start, end)
} }
for _, i := range rows { for _, i := range rows {
result[i.ID] = i result[i.ID] = i
...@@ -144,3 +144,39 @@ func GetUsers(model *domain.Model, ids []mysql.ID) ([]*User, error) { ...@@ -144,3 +144,39 @@ func GetUsers(model *domain.Model, ids []mysql.ID) ([]*User, error) {
} }
return res, nil return res, nil
} }
// 获取用户externalIds
// return []externalIds map[userId]extId map[userId]code
func GetUserExternalIds(model *domain.Model, userIds []mysql.ID) ([]string, map[uint64]string, map[uint64]string) {
var res []string
var m = make(map[uint64]string)
var c = make(map[uint64]string)
if len(userIds) <= 0 {
return res, m, c
}
var users []User
total := len(userIds)
const NUM = 500
start, end := 0, NUM
for start < total {
if end > total {
end = total
}
var tmp []User
tmpUserId := userIds[start:end]
if err := model.DB().Model(User{}).Where("id in (?)", tmpUserId).Select("id,external_id,code").Find(&tmp).Error; err != nil {
model.Log.Errorf("GetUserExternalIds fail:%v", err)
} else if len(tmp) > 0 {
users = append(users, tmp...)
}
start += NUM
end += NUM
}
for _, user := range users {
res = append(res, user.ExternalId)
m[user.ID] = user.ExternalId
c[user.ID] = user.Code
}
return res, m, c
}
...@@ -2,7 +2,6 @@ package user_m ...@@ -2,7 +2,6 @@ package user_m
import ( import (
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
...@@ -69,10 +68,7 @@ func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) { ...@@ -69,10 +68,7 @@ func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) {
end = len(userIds) end = len(userIds)
} }
start := 0 start := 0
for end <= len(userIds) { for start < len(userIds) {
if end > len(userIds) {
end = len(userIds)
}
tmp := make([]UserVip, 0) tmp := make([]UserVip, 0)
err := mysql.Db.Where("user_id IN ?", userIds[start:end]).Find(&tmp).Error err := mysql.Db.Where("user_id IN ?", userIds[start:end]).Find(&tmp).Error
if err != nil { if err != nil {
...@@ -85,7 +81,10 @@ func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) { ...@@ -85,7 +81,10 @@ func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) {
} }
start += 500 start += 500
end += 500 end += 500
mylogrus.MyLog.Infof("BatchGetVips start:%v-end:%v", start, end) if end > len(userIds) {
end = len(userIds)
}
//mylogrus.MyLog.Infof("BatchGetVips start:%v-end:%v", start, end)
} }
for _, i := range userIds { for _, i := range userIds {
......
...@@ -6,23 +6,18 @@ import ( ...@@ -6,23 +6,18 @@ import (
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/rpc" "git.hilo.cn/hilo-common/rpc"
"git.hilo.cn/hilo-common/sdk/tencentyun" "git.hilo.cn/hilo-common/sdk/tencentyun"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/msg_e" "hilo-group/_const/enum/msg_e"
"hilo-group/_const/enum/task_e" "hilo-group/_const/enum/task_e"
"hilo-group/domain/cache/group_c" "hilo-group/domain/cache/group_c"
"hilo-group/domain/event/gift_ev"
"hilo-group/domain/event/group_ev" "hilo-group/domain/event/group_ev"
"hilo-group/domain/event/group_power_ev" "hilo-group/domain/event/group_power_ev"
"hilo-group/domain/event/mic_ev"
"hilo-group/domain/model/diamond_m" "hilo-group/domain/model/diamond_m"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/model/mic_m"
"hilo-group/domain/model/msg_m" "hilo-group/domain/model/msg_m"
"hilo-group/domain/model/task_m" "hilo-group/domain/model/task_m"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/domain/service/group_mic_s"
"hilo-group/myerr" "hilo-group/myerr"
"strconv" "strconv"
"time" "time"
...@@ -34,8 +29,8 @@ func EventInit() { ...@@ -34,8 +29,8 @@ func EventInit() {
GroupEvents() GroupEvents()
GroupImMass() GroupImMass()
GroupTheme() GroupTheme()
SendGift() // 送礼事件 //SendGift() // 送礼事件
OnMic() // 在麦上事件 GroupInMicChangeEvent() // 用户进房推送mic位置信息
} }
func GroupSupportEvents() { func GroupSupportEvents() {
...@@ -470,101 +465,69 @@ func FlushHiloInfo(extId string, isVip bool, isPrettyCode bool, medals []uint32, ...@@ -470,101 +465,69 @@ func FlushHiloInfo(extId string, isVip bool, isPrettyCode bool, medals []uint32,
func SendGift() { func SendGift() {
// 送礼事件-势力经验 // 送礼事件-势力经验
gift_ev.AddSendGiftEventAsync(func(model *domain.Model, event interface{}) error { //gift_ev.AddSendGiftEventAsync(func(model *domain.Model, event interface{}) error {
sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent) // sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent)
if !ok { // if !ok {
model.Log.Errorf("AddSendGiftEventAsync event type err") // model.Log.Errorf("AddSendGiftEventAsync event type err")
return nil // return nil
} // }
model.Log.Infof("AddSendGiftEventAsync %+v", sendGiftEvent) // model.Log.Infof("AddSendGiftEventAsync %+v", sendGiftEvent)
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow { // if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return nil // return nil
} // }
exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId) // exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId)
if err != nil { // if err != nil {
model.Log.Infof("CheckGroupPowerUser fail %+v", err) // model.Log.Infof("CheckGroupPowerUser fail %+v", err)
return err // return err
} // }
if exist { // if exist {
exp := sendGiftEvent.GiftN * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) * sendGiftEvent.ResGift.DiamondNum // exp := sendGiftEvent.GiftN * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) * sendGiftEvent.ResGift.DiamondNum
return model.Transaction(func(model *domain.Model) error { // //return model.Transaction(func(model *domain.Model) error {
return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼") // // return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
}) // //})
} // return groupPower_c.QueueGroupPowerGradeExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
return nil // }
}) // return nil
//})
// 家族之星-送礼/收礼 // 家族之星-送礼/收礼
gift_ev.AddSendGiftEventAsync(func(model *domain.Model, event interface{}) error { //gift_ev.AddSendGiftEventAsync(func(model *domain.Model, event interface{}) error {
sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent) // sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent)
if !ok { // if !ok {
model.Log.Errorf("AddSendGiftEventAsync event type err") // model.Log.Errorf("AddSendGiftEventAsync event type err")
return nil // return nil
} // }
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow { // if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return nil // return nil
} // }
var userIds = []mysql.ID{sendGiftEvent.SendUserId} // var userIds = []mysql.ID{sendGiftEvent.SendUserId}
userIds = append(userIds, sendGiftEvent.ReceiveUserIds...) // userIds = append(userIds, sendGiftEvent.ReceiveUserIds...)
groupPowers, err := groupPower_m.BatchGetGroupPowerUser(model, userIds) // groupPowers, err := groupPower_m.BatchGetGroupPowerUser(model, userIds)
if err != nil { // if err != nil {
model.Log.Errorf("AddSendGiftEventAsync fail:%v", err) // model.Log.Errorf("AddSendGiftEventAsync fail:%v", err)
return err // return err
} // }
// 送礼加分 // // 送礼加分
if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok { // if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) // diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds))
if err := groupPower_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeFamous, diamonds, 0); err != nil { // if err := groupPower_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeFamous, diamonds, 0); err != nil {
model.Log.Errorf("IncrGroupPowerMonthStarScore famous fail:%v", err) // model.Log.Errorf("IncrGroupPowerMonthStarScore famous fail:%v", err)
} // }
if err := groupPower_m.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeFamous, diamonds, 0); err != nil { // if err := groupPower_m.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeFamous, diamonds, 0); err != nil {
model.Log.Errorf("IncrGroupPowerDayStarScore famous fail:%v", err) // model.Log.Errorf("IncrGroupPowerDayStarScore famous fail:%v", err)
} // }
} // }
// 收礼加分 // // 收礼加分
for _, userId := range sendGiftEvent.ReceiveUserIds { // for _, userId := range sendGiftEvent.ReceiveUserIds {
if data, ok := groupPowers[userId]; ok { // if data, ok := groupPowers[userId]; ok {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum // diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum
if err := groupPower_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeCharm, diamonds, 0); err != nil { // if err := groupPower_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeCharm, diamonds, 0); err != nil {
model.Log.Errorf("IncrGroupPowerMonthStarScore charm fail:%v", err) // model.Log.Errorf("IncrGroupPowerMonthStarScore charm fail:%v", err)
} // }
if err := groupPower_m.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeCharm, diamonds, 0); err != nil { // if err := groupPower_m.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeCharm, diamonds, 0); err != nil {
model.Log.Errorf("IncrGroupPowerDayStarScore charm fail:%v", err) // model.Log.Errorf("IncrGroupPowerDayStarScore charm fail:%v", err)
} // }
} // }
} // }
return nil // return nil
}) //})
}
func OnMic() {
// 上麦经验/上麦时长
mic_ev.AddOnMicEventAsync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*mic_ev.OnMicEvent)
if !ok {
model.Log.Errorf("AddOnMicEventSync event type err")
return nil
}
if err := group_mic_s.NewGroupPowerService(model.MyContext).IncrGroupPowerOnMicExpAndTime(event.GroupUuid, event.UserId, event.Timestamp); err != nil {
model.Log.Errorf("cron micIn GroupPowerOnMicExp err:%v", err)
} else {
model.Log.Infof("cron micIn GroupPowerOnMicExp success, groupId:%v, userId:%v", event.GroupUuid, event.UserId)
}
return nil
})
// 用户上麦时长
mic_ev.AddOnMicEventAsync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*mic_ev.OnMicEvent)
if !ok {
model.Log.Errorf("AddOnMicEventSync event type err")
return nil
}
if err := mic_m.IncrUserOnMic(model, event.UserId, event.Timestamp); err != nil {
model.Log.Errorf("cron micIn IncrUserOnMic err:%v", err)
} else {
model.Log.Infof("cron micIn IncrUserOnMic success,userId:%v", event.UserId)
}
// 处理活动数据 活动已经结束
//go rpc.AddActPoint(model, event.UserId, 1, 0)
return nil
})
} }
package event_s
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"golang.org/x/sync/errgroup"
"hilo-group/domain/event/group_ev"
"hilo-group/domain/model/event_m"
"runtime/debug"
)
type GroupInEventService struct {
svc *domain.Service
}
func NewGroupInEventService(myContext *mycontext.MyContext) *GroupInEventService {
svc := domain.CreateService(myContext)
return &GroupInEventService{svc}
}
//
func (s *GroupInEventService) Consume() error {
defer func() {
if err := recover(); err != nil {
s.svc.Log.Errorf("ExceptionHandle GroupInEventService Consume SYSTEM ACTION PANIC: %v, stack: %v", err, string(debug.Stack()))
}
}()
var model = domain.CreateModel(s.svc.CtxAndDb)
events, offset, err := event_m.FetchEventGroupIn(model, BatchCount)
if err != nil {
return err
}
var wg errgroup.Group
for k := range events {
cpEvent := &event_m.EventGroupIn{
Entity: mysql.Entity{
ID: events[k].ID,
CreatedTime: events[k].CreatedTime,
UpdatedTime: events[k].UpdatedTime,
},
Proto: events[k].Proto,
Payload: events[k].Payload,
Mark: events[k].Mark,
MarkHiloGroup: events[k].MarkHiloGroup,
}
wg.Go(func() error {
if cpEvent.MarkHiloGroup == mysql.YES {
model.Log.Warnf("already consume msg :%v", cpEvent)
return nil
}
groupInEvent := new(group_ev.TxGroupInEvent)
if err := json.Unmarshal(cpEvent.Payload, groupInEvent); err != nil {
model.Log.Errorf("json msg fail,event:%v,err:%v", cpEvent, err)
return nil
}
// 发布事件
if err := group_ev.PublishTxGroupInEvent(model, groupInEvent); err != nil {
model.Log.Errorf("PublishTxGroupInEvent,event:%v,err:%v", cpEvent, err)
return err
}
// 标记已经处理
cpEvent.Model = model
err = cpEvent.MarkDone()
if err != nil {
model.Log.Errorf("consume msg fail,event:%v,err:%v", cpEvent, err)
}
return err
})
}
err = wg.Wait()
if err != nil {
model.Log.Errorf("batch consume msg has fail,event,err:%v", err)
// 暂时先允许丢数据,继续mark offset
}
// 最后一次提交offset
if len(events) > 0 {
offset.MarkOffset = events[len(events)-1].ID
return offset.Persistence()
}
return nil
}
package event_s
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/protocol/userProxy"
"git.hilo.cn/hilo-common/rpc"
uuid "github.com/satori/go.uuid"
"hilo-group/domain/event/group_ev"
"hilo-group/domain/model/group_m"
"hilo-group/myerr/bizerr"
)
// 用户进房后推送mic信息
func GroupInMicChangeEvent() {
group_ev.AddTxGroupInEventAsync(func(model *domain.Model, event interface{}) error {
e, ok := event.(*group_ev.TxGroupInEvent)
if !ok {
return bizerr.InvalidParameter
}
return MicAllRPush(model, e.GroupId, e.UserId, e.ExternalId)
})
}
func MicAllRPush(model *domain.Model, imGroupId string, userId uint64, externalId string) error {
model.Log.Infof("MicChangeRPush MicAllRPush begin groupUuid:%v, externalId:%v", imGroupId, externalId)
txGroupId, err := group_m.ToTxGroupId(model, imGroupId)
if err != nil {
model.Log.Errorf("ToImGroupId fail:%v", err)
return err
}
//
micContents, err := group_m.GetMicAllContent(model, imGroupId)
if err != nil {
model.Log.Errorf("MicChangeRPush MicAllRPush getMicAllContent err:%+v, micContents:%v groupUuid:%v, externalId:%v", err, micContents, txGroupId, externalId)
return err
}
for _, micContent := range micContents {
//麦上是默认值,就不用推
if micContent.Forbid == false && micContent.User == nil && micContent.AgoraId == 0 && micContent.Lock == false && micContent.ExternalId == "" && micContent.MicForbid == false {
model.Log.Infof("MicChangeRPush MicAllRPush default micContent:%v, groupUuid:%v, externalId:%v, micContent:%+v", micContent, txGroupId, externalId, micContent)
continue
}
micContentStr, err := json.Marshal(micContent)
if err != nil {
continue
}
var micExternalId string
var micUserData *userProxy.MicUserData
if micContent.User != nil {
micExternalId = micContent.ExternalId
micUserData = &userProxy.MicUserData{
Id: micContent.User.Id,
ExternalId: micContent.User.ExternalId,
Avatar: micContent.User.Avatar,
Nick: micContent.User.Nick,
Sex: uint32(micContent.User.Sex),
Code: micContent.User.Code,
IsVip: micContent.User.IsVip,
Noble: uint32(micContent.User.NobleLeave),
HeadwearPicUrl: micContent.User.HeadwearPicUrl,
HeadwearEffectUrl: micContent.User.HeadwearEffectUrl,
HeadwearReverseEffectUrl: micContent.User.HeadwearReverseEffectUrl,
SvipLevel: uint32(micContent.User.SvipLevel),
MicEffect: micContent.User.MicEffect,
HeadwearIcon: micContent.User.HeadwearIcon,
Svip: nil,
}
if micContent.User.Svip.SvipLevel > 0 || len(micContent.User.Svip.Privileges) > 0 {
micUserData.Svip = &userProxy.Svip{
SvipLevel: uint64(micContent.User.SvipLevel),
}
for _, v := range micContent.User.Svip.Privileges {
micUserData.Svip.Privileges = append(micUserData.Svip.Privileges, &userProxy.SvipPrivilege{
Type: int32(v.Type),
CanSwitch: v.CanSwitch,
UserSwitch: v.UserSwitch,
MysteryCode: v.MysteryCode,
})
}
}
}
seqId := uuid.NewV4().String()
if err := rpc.SendSocketMicChange(seqId, userId, micExternalId, txGroupId, uint32(micContent.I), micContent.Lock, micContent.Forbid, micContent.MicForbid, micContent.AgoraId, micUserData); err != nil {
model.Log.Errorf("MicAllRPush err:%+v, groupUuid:%v, externalId:%v, micContent:%+v", err, txGroupId, externalId, string(micContentStr))
} else {
model.Log.Infof("MicChangeRPush MicAllRPush Marshal micContent, groupUuid:%v, externalId:%v, micContent:%+v", txGroupId, externalId, string(micContentStr))
}
}
model.Log.Infof("MicAllRPush end groupUuid:%v, externalId:%v", txGroupId, externalId)
return nil
}
...@@ -8,8 +8,10 @@ import ( ...@@ -8,8 +8,10 @@ import (
"git.hilo.cn/hilo-common/resource/redisCli" "git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/rpc" "git.hilo.cn/hilo-common/rpc"
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/event/group_ev" "hilo-group/domain/event/group_ev"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
...@@ -317,15 +319,13 @@ func (s *GroupMicService) IncrGroupPowerOnMicExpAndTime(groupId string, userId u ...@@ -317,15 +319,13 @@ func (s *GroupMicService) IncrGroupPowerOnMicExpAndTime(groupId string, userId u
return nil return nil
} }
// 增加势力上麦经验 // 增加势力上麦经验
if err := groupPower_m.IncrGroupPowerExpOnMic(model, groupPowerId, userId, joinMicTimestamp); err != nil { if err := groupPower_m.IncrGroupPowerExpOnMic(model, groupPowerId, userId); err != nil {
model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err) model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err)
} }
// 增加势力上麦时长-月 // 增加势力上麦时长-天/周/月
if err := groupPower_m.IncrGroupPowerStarOnMicMonth(model, groupPowerId, userId, joinMicTimestamp); err != nil { //if err := groupPower_m.IncrGroupPowerStarOnMicDay(model, groupPowerId, userId, joinMicTimestamp); err != nil {
model.Log.Errorf("IncrGroupPowerStarOnMicMonth fail:%v", err) if err := groupPower_c.IncrGroupPowerDayStarScore(model, groupPowerId, userId,
} groupPower_e.GroupPowerStarTypeActive, 60); err != nil {
// 增加势力上麦时长-天
if err := groupPower_m.IncrGroupPowerStarOnMicDay(model, groupPowerId, userId, joinMicTimestamp); err != nil {
model.Log.Errorf("IncrGroupPowerStarOnMicDay fail:%v", err) model.Log.Errorf("IncrGroupPowerStarOnMicDay fail:%v", err)
} }
return nil return nil
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"hilo-group/_const/enum/msg_e" "hilo-group/_const/enum/msg_e"
"hilo-group/cv/group_power_cv" "hilo-group/cv/group_power_cv"
"hilo-group/cv/user_cv" "hilo-group/cv/user_cv"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/cache/user_c" "hilo-group/domain/cache/user_c"
"hilo-group/domain/event/group_power_ev" "hilo-group/domain/event/group_power_ev"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
...@@ -154,7 +155,12 @@ func GetGroupPowerRankResp(model *domain.Model, beginDate, endDate string, userI ...@@ -154,7 +155,12 @@ func GetGroupPowerRankResp(model *domain.Model, beginDate, endDate string, userI
} }
func GetGroupPowerStar(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*group_power_cv.CvGroupPowerStarData, error) { func GetGroupPowerStar(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*group_power_cv.CvGroupPowerStarData, error) {
rank, err := groupPower_m.GetGroupPowerMonthStarRank(model, groupPowerId, _type, offset, limit, month) monthTime, err := time.Parse("200601", month)
if err != nil {
return nil, err
}
//rank, err := groupPower_m.GetGroupPowerMonthStarRank(model, groupPowerId, _type, offset, limit, month)
rank, err := groupPower_c.GetGroupPowerStarRankPeriod(model, "month", groupPowerId, _type, offset, limit, monthTime.Format("2006-01-02"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -4,8 +4,8 @@ import ( ...@@ -4,8 +4,8 @@ import (
"encoding/json" "encoding/json"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"gorm.io/gorm" "gorm.io/gorm"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/mgr_e" "hilo-group/_const/enum/mgr_e"
...@@ -18,7 +18,6 @@ import ( ...@@ -18,7 +18,6 @@ import (
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/domain/service/signal_s" "hilo-group/domain/service/signal_s"
"hilo-group/myerr" "hilo-group/myerr"
"strconv"
"time" "time"
) )
...@@ -31,7 +30,7 @@ func NewGroupService(myContext *mycontext.MyContext) *GroupService { ...@@ -31,7 +30,7 @@ func NewGroupService(myContext *mycontext.MyContext) *GroupService {
return &GroupService{svc} return &GroupService{svc}
} }
// 取本周最高的扶持等级 fixme:删除这个过渡函数 // 取本周最高的扶持等级
func (s *GroupService) GetWeekMaxSupportLevelMap() (map[string]uint8, error) { func (s *GroupService) GetWeekMaxSupportLevelMap() (map[string]uint8, error) {
return s.GetSupportLevelMap(time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY)) return s.GetSupportLevelMap(time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
} }
...@@ -42,56 +41,57 @@ func (s *GroupService) GetSupportLevelMap(now time.Time) (map[string]uint8, erro ...@@ -42,56 +41,57 @@ func (s *GroupService) GetSupportLevelMap(now time.Time) (map[string]uint8, erro
_, _, period := group_m.GetSupportLevelTime(now) _, _, period := group_m.GetSupportLevelTime(now)
levels, err := GetAllSupportLevel(model, period) levels, err := GetAllSupportLevel(model, period)
if err != nil {
return nil, err
}
model.Log.Debugf("GetSupportLevelMap, GET %s: %v", period, levels)
result := make(map[string]uint8, 0)
if len(levels) > 0 {
for g, l := range levels {
le, err := strconv.ParseUint(l, 10, 8)
if err == nil { if err == nil {
result[g] = uint8(le) return levels, nil
} }
} // cache miss
} else {
result, err = group_m.GetAllGroupSupportResult(model.Db, period) result, err := group_m.GetAllGroupSupportResult(model.Db, period)
if err == nil { if err == nil {
ret, err := SaveAllSupportLevel(model, period, result) SaveAllSupportLevel(model, period, result)
model.Log.Infof("GetSupportLevelMap SAVE ret = %d, err: %v", ret, err)
}
} }
return result, nil return result, nil
} }
func SaveAllSupportLevel(model *domain.Model, date string, levels map[string]uint8) (int64, error) { //// 取本周最高的扶持等级
values := make(map[string]interface{}, 0) //func (s *GroupService) GetWeekMaxSupportLevelMapByIds(groupIds []string) (map[string]uint8, error) {
for g, l := range levels { // return s.GetSupportLevelMapByIds(groupIds, time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
if l > 0 { //}
values[g] = l //
} //func (s *GroupService) GetSupportLevelMapByIds(groupIds []string, now time.Time) (map[string]uint8, error) {
} // model := domain.CreateModel(s.svc.CtxAndDb)
if len(values) <= 0 { //
return 0, nil // _, _, period := group_m.GetSupportLevelTime(now)
} //
key := redis_key.GetPrefixSupportLevel(date) // levels, err := GetAllSupportLevel(model, period)
ret, err := model.Redis.HSet(model, key, values).Result() // if err == nil {
// return levels, nil
// }
// // cache miss
//
// result, err := group_m.GetGroupSupportResult(model.DB(), period, groupIds)
// if err == nil {
// SaveAllSupportLevel(model, period, result)
// }
// return result, nil
//}
if err == nil { // supportLevelLru Cache
// 设置一个TTL保险一些 TODO: 可以优化,保证数据总是有的 var supportLevelCache = gcache.New(100).LRU().Build()
ttl := time.Hour
if !config.AppIsRelease() { func SaveAllSupportLevel(model *domain.Model, date string, levels map[string]uint8) {
ttl = time.Minute key := redis_key.GetPrefixSupportLevel(date)
} _ = supportLevelCache.SetWithExpire(key, levels, time.Hour)
model.Redis.Expire(model, key, ttl) return
}
return ret, err
} }
func GetAllSupportLevel(model *domain.Model, date string) (map[string]string, error) { func GetAllSupportLevel(model *domain.Model, date string) (map[string]uint8, error) {
key := redis_key.GetPrefixSupportLevel(date) key := redis_key.GetPrefixSupportLevel(date)
return model.Redis.HGetAll(model, key).Result() if data, err := supportLevelCache.Get(key); err == nil {
return data.(map[string]uint8), nil
} else {
return map[string]uint8{}, err
}
} }
func (s *GroupService) GetJoinGroupLimit(userId mysql.ID) (uint, error) { func (s *GroupService) GetJoinGroupLimit(userId mysql.ID) (uint, error) {
......
package group_s
import (
"context"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/_const/enum/gift_e"
"hilo-group/cv/gift_cv"
"hilo-group/domain/cache/room_c"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/res_m"
"sort"
"strconv"
"time"
)
func SortGroupCommonCountryList(model *domain.Model) {
// 常用的国家
countryMap := map[string]struct{}{"India": {}, "Indonesia": {}, "Iraq": {}, "KSA": {}, "Kuwait": {}, "Pakistan": {}, "Turkey": {}}
for country, _ := range countryMap {
sortGroupList, err := GetGroupSortList(model, country)
if err != nil {
model.Log.Errorf("SortGroupCommonCountryList err:%v", err)
return
}
// 写入redis
err = setToRedis(model, country, sortGroupList)
if err != nil {
model.Log.Errorf("SortGroupCommonCountryList country:%v, len(sortGroupList):%v, err:%v", country, len(sortGroupList), err)
return
}
time.Sleep(time.Second * 3)
}
}
func SortGroupNotCommonCountryList(model *domain.Model) {
// 常用的国家
countryMap := map[string]struct{}{"India": {}, "Indonesia": {}, "Iraq": {}, "KSA": {}, "Kuwait": {}, "Pakistan": {}, "Turkey": {}}
// 取所有的国家名字
allCountryList, err := res_m.GetCountryNameList(model)
if err != nil {
model.Log.Errorf("SortGroupNotCommonCountryList err:%v", err)
return
}
for _, country := range allCountryList {
if _, ok := countryMap[country]; ok {
continue
}
// 计算非常用国家
sortGroupList, err := GetGroupSortList(model, country)
if err != nil {
model.Log.Errorf("SortGroupNotCommonCountryList err:%v", err)
return
}
// 写入redis
err = setToRedis(model, country, sortGroupList)
if err != nil {
model.Log.Errorf("SortGroupNotCommonCountryList country:%v, len(sortGroupList):%v, err:%v", country, len(sortGroupList), err)
return
}
time.Sleep(time.Second * 5)
}
}
func setToRedis(model *domain.Model, country string, groupList []string) error {
// 写入redis
key := rediskey.GetGroupCountrySortList(country)
for idx, group := range groupList {
err := model.RedisCluster.ZRemRangeByRank(context.Background(), key, int64(idx), int64(idx)).Err() // 先删除旧的
if err != nil {
model.Log.Errorf("setToRedis SortGroup key:%v, idx:%v, err:%v", key, idx, err)
return err
}
// 插入
err = model.RedisCluster.ZAdd(context.Background(), key, &redis.Z{Score: float64(idx), Member: group}).Err()
if err != nil {
model.Log.Errorf("setToRedis SortGroup key:%v, idx:%v, group:%s, err:%v", key, idx, group, err)
return err
}
if idx%1000 == 0 {
time.Sleep(time.Millisecond * 50)
}
}
return nil
}
// 计算国家群组列表排序
func GetGroupSortList(model *domain.Model, country string) ([]string, error) {
bannedGroups, err := group_m.GetBannedGroupsMap(model)
if err != nil {
return nil, err
}
beginTime := time.Now()
groups, banCount, visitCount, err := GetCandidatesByCountry(model, bannedGroups, country)
if err != nil {
return nil, err
}
endTime := time.Now()
model.Log.Infof("GroupCountryListSort: candidates size = %d, takes %d ms banned = %d, visitCount size = %d",
len(groups), endTime.Sub(beginTime).Milliseconds(), banCount, len(visitCount))
// 获取麦上有人的所有群组及麦上人数
micGroupNum, err := group_m.GetMicHasInGroupNum(model)
if err != nil {
return nil, err
}
model.Log.Infof("GroupCountryListSort, micGroupNum : %v", micGroupNum)
model.Log.Infof("GroupCountryListSort cost2:%v", time.Now().Sub(beginTime))
sortedGroupIds := make([]string, 0)
diamondGroupIds := make([]string, 0)
for i, _ := range groups {
// 麦上没人也放出来
sortedGroupIds = append(sortedGroupIds, i)
// 麦上有人才计算流水
if micGroupNum[i] > 0 {
diamondGroupIds = append(diamondGroupIds, i)
}
}
now := time.Now()
bTime := now.Add(-time.Minute * 30)
g := gift_cv.GiftOperate{SceneType: gift_e.GroupSceneType}
diamonds, err := g.GetRangeConsumeSummaryV2(bTime, now, diamondGroupIds)
if err != nil {
return nil, err
}
model.Log.Infof("GroupCountryListSort, diamonds in 30 mins: %v", diamonds)
model.Log.Infof("GroupCountryListSort cost3:%v", time.Now().Sub(beginTime))
//supportLevels, err := NewGroupService(model.MyContext).GetWeekMaxSupportLevelMap()
//if err != nil {
// return nil, err
//}
//model.Log.Infof("GroupCountryListSort, supportLevels : %v", supportLevels)
model.Log.Infof("GroupCountryListSort cost4:%v", time.Now().Sub(beginTime))
// 排序优先级2022-07-25
sort.Slice(sortedGroupIds, func(i, j int) bool {
gi := sortedGroupIds[i]
gj := sortedGroupIds[j]
// 1、按麦上人数多少排序
if micGroupNum[gi] > micGroupNum[gj] {
return true
} else if micGroupNum[gi] < micGroupNum[gj] {
return false
}
// 2、麦上人数相同,按30分钟内送礼钻石数排序
if diamonds[gi] > diamonds[gj] {
return true
} else if diamonds[gi] < diamonds[gj] {
return false
}
// 3. 根据热度排序groupInUserDuration
if visitCount[gi] > visitCount[gj] {
return true
} else if visitCount[gi] < visitCount[gj] {
return false
}
// * Final resort: 群组CODE,短号优先,然后按字母序
return len(groups[gi].Code) < len(groups[gj].Code) || len(groups[gi].Code) == len(groups[gj].Code) && groups[gi].Code < groups[gj].Code
})
model.Log.Infof("GroupCountryListSort cost5:%v", time.Now().Sub(beginTime))
return sortedGroupIds, nil
}
// 国家群候选:没有密码且没被封禁的群, 有国家
func GetCandidatesByCountry(model *domain.Model, bannedGroups map[string]uint64, country string) (map[string]*group_m.GroupInfo, int, map[string]int64, error) {
noPwdGroups, err := group_m.FindOwnerCountryGroups(model, country)
if err != nil {
return nil, 0, nil, err
}
var groupIds []string
for _, v := range noPwdGroups {
groupIds = append(groupIds, v.ImGroupId) // imGroupId
}
//roomVisitCount, err := room_c.GetAllRoomVisitCount()
roomVisitCount, err := room_c.MGetRoomVisitCount(groupIds)
if err != nil {
return nil, 0, nil, err
}
gameRoom := group_m.GetGameGroupsMap(model)
banCount := 0
groups := make(map[string]*group_m.GroupInfo, 0)
visitCount := make(map[string]int64)
for i, v := range noPwdGroups {
// 过滤掉被封禁的群
if bannedGroups[v.ImGroupId] != 0 {
banCount++
continue
}
// 过滤游戏房
if gameRoom[v.ImGroupId] {
continue
}
// 先从二级缓存中找
if c, ok := roomVisitCount[v.ImGroupId]; ok {
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
//model.Log.Debugf("getPopularCandidates, from roomVisitCount %s(%s) - %d", v.ImGroupId, v.Code, vc)
groups[v.ImGroupId] = &noPwdGroups[i]
visitCount[v.ImGroupId] = vc
}
} else {
// 如果没有,就从roomVisit中取
if vc, err := room_c.GetSetRoomVisitCount(v.ImGroupId); err == nil && vc > 0 {
model.Log.Infof("getPopularCandidates, from roomVisit %s(%s) - %d", v.ImGroupId, v.Code, vc)
groups[v.ImGroupId] = &noPwdGroups[i]
visitCount[v.ImGroupId] = vc
}
}
}
return groups, banCount, visitCount, nil
}
func GetVisitCount(groupIds []string) (map[string]int64, error) {
roomVisitCount, err := room_c.MGetRoomVisitCount(groupIds)
if err != nil {
return nil, err
}
visitCount := make(map[string]int64)
for _, v := range groupIds {
// 先从二级缓存中找
if c, ok := roomVisitCount[v]; ok {
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
visitCount[v] = vc
}
} else {
// 如果没有,就从roomVisit中取
if vc, err := room_c.GetSetRoomVisitCount(v); err == nil && vc > 0 {
visitCount[v] = vc
}
}
}
return visitCount, nil
}
...@@ -17,7 +17,9 @@ import ( ...@@ -17,7 +17,9 @@ import (
"git.hilo.cn/hilo-common/utils" "git.hilo.cn/hilo-common/utils"
"gorm.io/gorm" "gorm.io/gorm"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/msg_e"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/group_k"
"hilo-group/common" "hilo-group/common"
"hilo-group/cv/property_cv" "hilo-group/cv/property_cv"
"hilo-group/domain/cache/group_c" "hilo-group/domain/cache/group_c"
...@@ -32,6 +34,7 @@ import ( ...@@ -32,6 +34,7 @@ import (
"hilo-group/myerr" "hilo-group/myerr"
"hilo-group/myerr/bizerr" "hilo-group/myerr/bizerr"
"strconv" "strconv"
"strings"
"time" "time"
) )
...@@ -509,3 +512,118 @@ func dealActDataAfterEnterRoom(myContext *mycontext.MyContext, userId, rideId ui ...@@ -509,3 +512,118 @@ func dealActDataAfterEnterRoom(myContext *mycontext.MyContext, userId, rideId ui
go rpc.AddActPoint(domain.CreateModelContext(myContext), userId, 5, roomId) go rpc.AddActPoint(domain.CreateModelContext(myContext), userId, 5, roomId)
} }
} }
// 创建房间,慎用
func (s *GroupService) CreateGroupMulByUid(userId uint64, num int, micNumType group_e.GroupMicNumType) error {
model := domain.CreateModel(s.svc.CtxAndDb)
if lock := redisCli.Lock(group_k.GetGroupLockKey(userId), time.Second*5); !lock {
return bizerr.ReqTooFrequent
}
user, err := user_m.GetUser(model, userId)
if err != nil {
model.Log.Errorf("CreateGroupMulByUid err:%v", err)
return err
}
// 强行修正为英语,以保证建群成功
user.Language = utils.DEFAULT_LANG
// 群组的头像默认为用户头像,群组的名称默认为用户昵称,群简介默认为“s%的群组”,群公告默认为“欢迎来到Hilo”
name := ""
text := res_m.ResMultiText{MsgId: msg_e.MSG_ID_GROUP_NAME, Language: user.Language}
if text.Get(model.Db) == nil {
name = strings.ReplaceAll(text.Content, "{nick}", user.Nick)
}
introduction := ""
text2 := res_m.ResMultiText{MsgId: msg_e.MSG_ID_GROUP_INTRODUCTION, Language: user.Language}
if text2.Get(model.Db) == nil {
introduction = strings.ReplaceAll(text2.Content, "{nick}", user.Nick)
}
notification := ""
text3 := res_m.ResMultiText{MsgId: msg_e.MSG_ID_GROUP_NOTIFICATION, Language: user.Language}
if text3.Get(model.Db) == nil {
notification = strings.ReplaceAll(text3.Content, "{nick}", user.Nick)
}
faceUrl := user.Avatar
for idx := 0; idx < num; idx++ {
code := group_m.GenerateGroupCode(group_e.GROUP_DEFAULT_CODE_LENGTH)
i := 0
for ; i < group_e.CREATE_GROUP_MAX_ATTEMPT; i++ {
success, err := res_m.CheckCode(model, code)
if err != nil || !success {
break
}
r, err := group_m.FindGroupByCode(model, code)
if err == nil && r == nil {
break
}
code = group_m.GenerateGroupCode(group_e.GROUP_DEFAULT_CODE_LENGTH)
}
if i >= group_e.CREATE_GROUP_MAX_ATTEMPT {
return myerr.NewSysError("Failed in generating groupId")
}
groupId := group_e.OverseaGroupNamePrefix + code
groupId, err = tencentyun.CreateGroup(name, groupId)
if err != nil {
model.Log.Errorf("CreateGroupMulByUid err:%v", err)
return err
}
channelId := utils.GetUUID()
_, _, err = agora.CreateGroupAgora(channelId, uint32(userId))
if err != nil {
// 回滚,删除刚刚建立的TX群组
tencentyun.DestroyGroup(groupId, false)
model.Log.Errorf("CreateGroupMulByUid err:%v", err)
return err
}
roomType := group_e.OverseaRoom
g := group_m.GroupInfo{
ImGroupId: groupId,
TxGroupId: groupId,
Type: uint16(roomType),
Code: code,
OriginCode: code,
Owner: userId,
Name: name,
Introduction: introduction,
Notification: notification,
FaceUrl: faceUrl,
Country: user.Country,
ChannelId: channelId,
MicOn: true,
LoadHistory: false,
MicNumType: micNumType,
TouristMic: 1,
TouristSendMsg: 1,
TouristSendPic: 1,
IsGameRoom: 1,
}
if err := s.CreateGroup(userId, &g); err != nil {
// 回滚,删除刚刚建立的TX群组
tencentyun.DestroyGroup(groupId, false)
model.Log.Errorf("CreateGroupMulByUid err:%v", err)
return err
}
gm := group_m.GroupMember{
GroupId: groupId,
UserId: userId,
}
if err = gm.Create(model.Db); err != nil {
model.Log.Warnf("Failed to set GroupMember +%v", gm)
}
time.Sleep(time.Millisecond * 30)
}
return nil
}
This diff is collapsed.
...@@ -93,6 +93,7 @@ require ( ...@@ -93,6 +93,7 @@ require (
github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 // indirect github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect github.com/ugorji/go/codec v1.1.7 // indirect
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/text v0.3.6 // indirect golang.org/x/text v0.3.6 // indirect
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e // indirect golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e // indirect
......
...@@ -401,6 +401,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ ...@@ -401,6 +401,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
......
...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code ...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS] [REDIS]
REDIS_HOST=47.244.34.27:6379 REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT] [JWT]
SECRET=hilo1632 SECRET=hilo1632
ISSUER_API=hiloApi ISSUER_API=hiloApi
......
...@@ -3,6 +3,7 @@ package main ...@@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"git.hilo.cn/hilo-common/resource/consul" "git.hilo.cn/hilo-common/resource/consul"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-group/cron" "hilo-group/cron"
"hilo-group/domain/service/event_s" "hilo-group/domain/service/event_s"
"hilo-group/route" "hilo-group/route"
...@@ -17,6 +18,7 @@ const ( ...@@ -17,6 +18,7 @@ const (
func main() { func main() {
cron.Init() // 开启定时任务 cron.Init() // 开启定时任务
event_s.EventInit() // 注册事件(内部事件+mysql拟kafka) event_s.EventInit() // 注册事件(内部事件+mysql拟kafka)
redisCli.InitCluster() // redis集群
r := route.InitRouter() // 注册路由 r := route.InitRouter() // 注册路由
consul.RegisterToConsul(PORT, RegisterName, RegisterTag) // 服务注册 consul.RegisterToConsul(PORT, RegisterName, RegisterTag) // 服务注册
r.Run(fmt.Sprintf(":%d", PORT)) // 启动服务 r.Run(fmt.Sprintf(":%d", PORT)) // 启动服务
......
...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code ...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS] [REDIS]
REDIS_HOST=r-eb3btxn8vfdsuwdbuf.redis.dubai.rds.aliyuncs.com:6379 REDIS_HOST=r-eb3btxn8vfdsuwdbuf.redis.dubai.rds.aliyuncs.com:6379
REDIS_PASSWORD= REDIS_PASSWORD=
REDIS_CLUSTER_HOST=r-eb3yt6k8zgxs62kjjs.redis.dubai.rds.aliyuncs.com:6379
REDIS_CLUSTER_PASSWORD=
[JWT] [JWT]
SECRET=hilo1504 SECRET=hilo1504
ISSUER_API=hiloApi ISSUER_API=hiloApi
......
...@@ -23,6 +23,7 @@ import ( ...@@ -23,6 +23,7 @@ import (
"hilo-group/cv/group_power_cv" "hilo-group/cv/group_power_cv"
"hilo-group/cv/medal_cv" "hilo-group/cv/medal_cv"
"hilo-group/cv/user_cv" "hilo-group/cv/user_cv"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/cache/res_c" "hilo-group/domain/cache/res_c"
"hilo-group/domain/cache/user_c" "hilo-group/domain/cache/user_c"
"hilo-group/domain/model/game_m" "hilo-group/domain/model/game_m"
...@@ -820,7 +821,7 @@ func GroupPowerInfo(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -820,7 +821,7 @@ func GroupPowerInfo(c *gin.Context) (*mycontext.MyContext, error) {
} }
} }
// 补上家族之星三个榜一 // 补上家族之星三个榜一
stars, err := groupPower_m.GetGroupPowerMonthStartTop1(model, gp.ID) stars, err := groupPower_c.GetGroupPowerMonthStartTop1(model, gp.ID)
if err != nil { if err != nil {
return myContext, myerr.WrapErr(err) return myContext, myerr.WrapErr(err)
} }
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"hilo-group/_const/enum/groupPower_e" "hilo-group/_const/enum/groupPower_e"
"hilo-group/cv/group_power_cv" "hilo-group/cv/group_power_cv"
"hilo-group/cv/user_cv" "hilo-group/cv/user_cv"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/domain/service/group_power_s" "hilo-group/domain/service/group_power_s"
...@@ -264,7 +265,7 @@ func GroupPowerStarPeriod(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -264,7 +265,7 @@ func GroupPowerStarPeriod(c *gin.Context) (*mycontext.MyContext, error) {
} }
var model = domain.CreateModelContext(myContext) var model = domain.CreateModelContext(myContext)
offset, limit := (param.PageIndex-1)*param.PageSize, param.PageSize offset, limit := (param.PageIndex-1)*param.PageSize, param.PageSize
rank, err := groupPower_m.GetGroupPowerStarRankPeriod(model, period, param.GroupPowerId, param.Type, offset, limit) rank, err := groupPower_c.GetGroupPowerStarRankPeriod(model, period, param.GroupPowerId, param.Type, offset, limit)
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
......
package group_power_r package group_power_r
import ( import (
"fmt"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/jinzhu/now"
"hilo-group/_const/enum/groupPower_e" "hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/enum/msg_e" "hilo-group/_const/enum/msg_e"
"hilo-group/_const/redis_key/groupPower_k"
"hilo-group/cv/group_power_cv" "hilo-group/cv/group_power_cv"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/msg_m" "hilo-group/domain/model/msg_m"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/domain/service/group_power_s" "hilo-group/domain/service/group_power_s"
"hilo-group/myerr/bizerr"
"hilo-group/resp" "hilo-group/resp"
"time"
) )
type MGetGroupPowerReq struct { type MGetGroupPowerReq struct {
...@@ -93,3 +98,66 @@ func Test(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -93,3 +98,66 @@ func Test(c *gin.Context) (*mycontext.MyContext, error) {
//} //}
return nil, nil return nil, nil
} }
type GroupPowerDayStar struct {
Date time.Time
GroupPowerId uint64
Type groupPower_e.GroupPowerStarType
UserId uint64
Score uint64
}
// @Tags 国家势力-内部
// @Summary 同步家族之星到redis
// @Success 200
// @Router /inner/groupPower/sync/star [get]
func SyncStar(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
t := time.Now()
start := c.Query("start")
end := c.Query("end")
if len(start) <= 0 || len(end) <= 0 {
return myCtx, bizerr.InvalidParameter
}
var model = domain.CreateModelContext(myCtx)
var stars []GroupPowerDayStar
if err := model.DB().Table("group_power_day_star").
Select("`date`,group_power_id,type,user_id,SUM(score) score").
Where("`date` BETWEEN ? AND ?", start, end).
Group("`date`,group_power_id,type,user_id").Find(&stars).Error; err != nil {
model.Log.Errorf("SyncStar fail:%v", err)
return myCtx, err
}
ttl := map[string]time.Duration{
"day": time.Hour * 24 * 7,
"week": time.Hour * 24 * 7 * 30,
"month": time.Hour * 24 * 7 * 30 * 2,
}
num := len(stars)
for i, star := range stars {
for _, period := range []string{"day", "week", "month"} {
var dateStr string
switch period {
case "day":
dateStr = star.Date.Format("2006-01-02")
case "week":
dateStr = now.With(star.Date).BeginningOfWeek().Format("2006-01-02")
case "month":
dateStr = now.With(star.Date).BeginningOfMonth().Format("2006-01-02")
}
key := groupPower_k.GetGroupPowerStarRankKey(star.Type, period, star.GroupPowerId, dateStr)
model.RedisCluster.ZIncrBy(model, key, float64(star.Score), fmt.Sprintf("%d", star.UserId))
model.RedisCluster.Expire(model, key, ttl[period])
model.Log.Infof("SyncStar i:%v,star:%v", i, star)
}
}
type res struct {
Num int
Cost float64
}
resp.ResponseOk(c, res{
Num: num,
Cost: time.Now().Sub(t).Seconds(),
})
return myCtx, nil
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code ...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS] [REDIS]
REDIS_HOST=47.244.34.27:6379 REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT] [JWT]
SECRET=hilo1632 SECRET=hilo1632
ISSUER_API=hiloApi ISSUER_API=hiloApi
......
This diff is collapsed.