...
 
Commits (197)
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)
}
package group_k
import (
"fmt"
"hilo-group/_const/redis_key"
)
// 用户进房的key
const (
UserEnterRoomPrefix = "uer:"
UserEnterRoomUserKey = UserEnterRoomPrefix + "u:${user_id}"
UserEnterRoomGroupKey = UserEnterRoomPrefix + "g:${group_id}"
)
func GetUserEnterRoomUserKey(userId uint64) string {
return redis_key.ReplaceKey(UserEnterRoomUserKey, fmt.Sprintf("%d", userId))
}
func GetUserEnterRoomGroupKey(groupId string) string {
return redis_key.ReplaceKey(UserEnterRoomGroupKey, groupId)
}
...@@ -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()
} }
...@@ -30,6 +30,7 @@ func GiftRemark() { ...@@ -30,6 +30,7 @@ func GiftRemark() {
Payload: unmark.Payload, Payload: unmark.Payload,
MarkHiloGroup: unmark.MarkHiloGroup, MarkHiloGroup: unmark.MarkHiloGroup,
Mark: unmark.Mark, // 不能影响别的服务的mark状态 Mark: unmark.Mark, // 不能影响别的服务的mark状态
MarkHiloUser: unmark.MarkHiloUser,
}); err != nil { }); err != nil {
model.Log.Errorf("FetchUnMarkEvent add unmark fail:%v", err) model.Log.Errorf("FetchUnMarkEvent add unmark fail:%v", err)
continue continue
......
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
}
package group_c
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"github.com/spf13/cast"
"hilo-group/_const/redis_key/group_k"
"strconv"
"time"
)
// 用户进房
func ZAddUserEnterRoom(model *domain.Model, userId uint64, imGroupId string) {
userKey := group_k.GetUserEnterRoomUserKey(userId)
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
if err := model.Redis.ZAdd(model, userKey, &redis.Z{
Score: float64(time.Now().Unix()),
Member: imGroupId,
}).Err(); err != nil {
model.Log.Errorf("ZAddUserEnterRoom user fail:%v", err)
}
if err := model.Redis.ZAdd(model, groupKey, &redis.Z{
Score: float64(time.Now().Unix()),
Member: userId,
}).Err(); err != nil {
model.Log.Errorf("ZAddUserEnterRoom room fail:%v", err)
}
}
// 获取最近房间访客
// 15天
func GetLastRoomVisitors(model *domain.Model, imGroupId string) (userIds []uint64) {
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
res, err := model.Redis.ZRangeByScore(model, groupKey, &redis.ZRangeBy{
Min: fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix()),
Max: "+inf",
}).Result()
if err != nil {
return
}
for _, u := range res {
uid, _ := strconv.ParseUint(u, 10, 64)
if uid > 0 {
userIds = append(userIds, uid)
}
}
return
}
// 获取最近进入的房间
// 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)
res, err := model.Redis.ZRevRangeByScoreWithScores(model, userKey, &redis.ZRangeBy{
Min: fmt.Sprintf("%d", time.Now().AddDate(0, -3, 0).Unix()),
Max: "+inf",
Offset: offset,
Count: limit,
}).Result()
if err != nil {
return
}
for _, v := range res {
imGroupId := cast.ToString(v.Member)
imGroupIds = append(imGroupIds, imGroupId)
roomEnterTime[imGroupId] = int64(v.Score)
}
return
}
// 清理房间访客
// 15天前访问的
func RemoveRoomVisitors(model *domain.Model, imGroupId string) {
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
n, err := model.Redis.ZRemRangeByScore(model, groupKey, "-inf", fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix())).Result()
if err != nil {
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
...@@ -16,6 +16,7 @@ type EventGiftSend struct { ...@@ -16,6 +16,7 @@ type EventGiftSend struct {
Payload []byte Payload []byte
Mark mysql.YesNo Mark mysql.YesNo
MarkHiloGroup mysql.YesNo MarkHiloGroup mysql.YesNo
MarkHiloUser mysql.YesNo
} }
func (EventGiftSend) TableName() string { func (EventGiftSend) TableName() string {
......
...@@ -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:"->"`
}
// 增加家族经验 // 增加家族经验
// 达到经验值之后升级 // 达到经验值之后升级
// 单进程同步执行,不考虑并发 // 单进程同步执行,不考虑并发
...@@ -82,17 +64,34 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N ...@@ -82,17 +64,34 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N
return err return err
} }
// 增加家族经验-总 // 增加家族经验-总
gpg := &GroupPowerGrade{ gpg := new(GroupPowerGrade)
// insert
if err := txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(gpg).Error; err != nil {
if err != gorm.ErrRecordNotFound {
return err
}
// gorm.ErrRecordNotFound
gpg = &GroupPowerGrade{
GroupPowerId: groupPowerId, GroupPowerId: groupPowerId,
Exp: exp, Exp: exp,
Grade: 0, Grade: 0,
ExpireAt: time.Time{}, ExpireAt: time.Time{},
} }
if err = txModel.DB().Model(GroupPowerGrade{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "group_power_id"}}, if err = txModel.DB().Create(gpg).Error; err != nil {
DoUpdates: clause.Assignments(map[string]interface{}{ return err
"exp": gorm.Expr("exp + ?", gpg.Exp)})}).Create(gpg).Error; err != nil { }
} else {
// or update
if err := txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).
UpdateColumn("exp", gorm.Expr("exp + ?", exp)).Error; err != nil {
return err return err
} }
}
//if err = txModel.DB().Model(GroupPowerGrade{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "group_power_id"}},
// DoUpdates: clause.Assignments(map[string]interface{}{
// "exp": gorm.Expr("exp + ?", gpg.Exp)})}).Create(gpg).Error; err != nil {
// return err
//}
// 当前写后读 // 当前写后读
latestGrade := new(GroupPowerGrade) latestGrade := new(GroupPowerGrade)
if err = txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(latestGrade).Error; err != nil { if err = txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(latestGrade).Error; err != nil {
...@@ -135,154 +134,24 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N ...@@ -135,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
})
} }
// 清理所有家族的经验 // 清理所有家族的经验
......
...@@ -15,9 +15,11 @@ type GroupPowerExpRank struct { ...@@ -15,9 +15,11 @@ type GroupPowerExpRank struct {
// 获取家族经验排行榜 // 获取家族经验排行榜
// param limit: 排行榜人数 // param limit: 排行榜人数
// 10166 线上员工,对应的势力不上榜,groupPowerId=8951
func GetGroupPowerExpRank(model *domain.Model, beginDate, endDate string, limit int, gpStatus groupPower_e.GroupPowerStatus, area int) ([]GroupPowerExpRank, error) { func GetGroupPowerExpRank(model *domain.Model, beginDate, endDate string, limit int, gpStatus groupPower_e.GroupPowerStatus, area int) ([]GroupPowerExpRank, error) {
var res []GroupPowerExpRank var res []GroupPowerExpRank
db := model.DB().Table("group_power_day_exp gpd").Select("gpd.group_power_id,SUM(gpd.exp) as exp"). db := model.DB().Table("group_power_day_exp gpd").Select("gpd.group_power_id,SUM(gpd.exp) as exp").
Where("gpd.group_power_id <> 8951").
Where("gpd.date BETWEEN ? AND ?", beginDate, endDate) Where("gpd.date BETWEEN ? AND ?", beginDate, endDate)
if gpStatus > 0 { if gpStatus > 0 {
db = db.Joins("left join group_power gp on gpd.group_power_id = gp.id").Where("gp.status = ?", gpStatus) db = db.Joins("left join group_power gp on gpd.group_power_id = gp.id").Where("gp.status = ?", gpStatus)
......
...@@ -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()
...@@ -455,6 +470,7 @@ func GetMicUser(model *domain.Model, groupUuid string, i int) (*MicUser, error) ...@@ -455,6 +470,7 @@ func GetMicUser(model *domain.Model, groupUuid string, i int) (*MicUser, error)
I: i, I: i,
ExternalId: micUser.ExternalId, ExternalId: micUser.ExternalId,
UserId: micUser.UserId, UserId: micUser.UserId,
CpUserId: micUser.CpUserId,
Forbid: micUser.Forbid, Forbid: micUser.Forbid,
Timestamp: micUser.Timestamp, Timestamp: micUser.Timestamp,
}, nil }, nil
......
...@@ -3,6 +3,8 @@ package group_m ...@@ -3,6 +3,8 @@ package group_m
import ( import (
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"time"
) )
type GroupBanned struct { type GroupBanned struct {
...@@ -24,12 +26,19 @@ func (banned *GroupBanned) Delete(model *domain.Model) error { ...@@ -24,12 +26,19 @@ func (banned *GroupBanned) Delete(model *domain.Model) error {
return model.Db.Where(banned).Delete(&GroupBanned{}).Error return model.Db.Where(banned).Delete(&GroupBanned{}).Error
} }
var bannedGroupCache = gcache.New(100).LRU().Build()
func GetBannedGroups(model *domain.Model) ([]GroupBanned, error) { func GetBannedGroups(model *domain.Model) ([]GroupBanned, error) {
key := "banned"
if data, err := bannedGroupCache.Get(key); err == 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
} }
bannedGroupCache.SetWithExpire(key, result, time.Minute*5)
return result, nil return result, nil
} }
......
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 {
......
...@@ -23,9 +23,13 @@ func (g *GroupTop) Delete(model *domain.Model) error { ...@@ -23,9 +23,13 @@ func (g *GroupTop) Delete(model *domain.Model) error {
return model.Db.Where(g).Delete(&GroupTop{}).Error return model.Db.Where(g).Delete(&GroupTop{}).Error
} }
func GroupTopGetAll(model *domain.Model) ([]string, error) { func GroupTopGetAll(model *domain.Model, area int) ([]string, error) {
rows := make([]GroupTop, 0) rows := make([]GroupTop, 0)
err := model.Db.Order("id").Find(&rows).Error err := model.DB().Table("group_top").
Joins("left join group_info gi on group_top.im_group_id = gi.im_group_id "+
"left join res_country rc on gi.country = rc.name").
Where("rc.area = ?", area).
Order("group_top.id").Find(&rows).Error
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
package group_m
import (
"git.hilo.cn/hilo-common/domain"
"hilo-group/_const/enum/group_e"
"hilo-group/myerr"
"math/rand"
"time"
)
type GroupIm struct {
Id uint64
Provider group_e.GroupProvider
Prob int
StartIdx int `gorm:"-"'`
EndIdx int `gorm:"-"`
}
type GroupImLog struct {
ImGroupId string
Provider group_e.GroupProvider
}
func GetGroupImConf(model *domain.Model) ([]*GroupIm, error) {
rows := make([]*GroupIm, 0)
if err := model.Db.Table("group_im").Find(&rows).Error; err != nil {
return nil, myerr.WrapErr(err)
}
return rows, nil
}
func GetRandomImProvider(model *domain.Model) group_e.GroupProvider {
var res group_e.GroupProvider
confList, err := GetGroupImConf(model)
if err != nil {
model.Log.Errorf("GetRandomImProvider err:%v", err)
return res
}
conf := GetRandomGroupImConf(confList)
return conf.Provider
}
func GetRandomGroupImConf(confList []*GroupIm) *GroupIm {
var res *GroupIm
var max int
for i, v := range confList {
if v.Prob > 0 {
confList[i].StartIdx = max
max += v.Prob
confList[i].EndIdx = max
}
}
rand.Seed(time.Now().UnixNano())
randNum := rand.Intn(max)
for _, v := range confList {
if v.StartIdx <= randNum && randNum < v.EndIdx {
res = v
}
}
return res
}
func CreateGroupImLog(model *domain.Model, imGroupId string, provider group_e.GroupProvider) error {
if err := model.Db.Model(GroupImLog{}).Create(GroupImLog{ImGroupId: imGroupId, Provider: provider}).Error; err != nil {
return myerr.WrapErr(err)
}
return nil
}
This diff is collapsed.
This diff is collapsed.
...@@ -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)
...@@ -505,7 +493,8 @@ func (uer *UserEnterRoom) Save(db *gorm.DB) error { ...@@ -505,7 +493,8 @@ func (uer *UserEnterRoom) Save(db *gorm.DB) error {
func (uer *UserEnterRoom) Find(db *gorm.DB) ([]UserEnterRoom, error) { func (uer *UserEnterRoom) Find(db *gorm.DB) ([]UserEnterRoom, error) {
rows := make([]UserEnterRoom, 0) rows := make([]UserEnterRoom, 0)
if err := db.Where(uer).Order("enter_time DESC").Find(&rows).Error; err != nil { t := time.Now().AddDate(0, 0, -15)
if err := db.Where(uer).Where("enter_time >= ?", t).Order("enter_time DESC").Find(&rows).Error; err != nil {
return nil, err return nil, err
} }
return rows, nil return rows, nil
......
...@@ -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)
}
...@@ -14,6 +14,7 @@ type ResHeadwear struct { ...@@ -14,6 +14,7 @@ type ResHeadwear struct {
Name mysql.Str Name mysql.Str
PicUrl mysql.Str PicUrl mysql.Str
EffectUrl mysql.Str EffectUrl mysql.Str
ReverseEffectUrl mysql.Str
} }
func GetResHeadwearById(model *domain.Model, id mysql.ID) (*ResHeadwear, error) { func GetResHeadwearById(model *domain.Model, id mysql.ID) (*ResHeadwear, error) {
......
...@@ -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()
} }
...@@ -3,10 +3,12 @@ package user_m ...@@ -3,10 +3,12 @@ package user_m
import ( import (
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/myerr" "hilo-group/myerr"
) )
//获取用户的国家,和所属的区域(是否阿语区) // 获取用户的国家,和所属的区域(是否阿语区)
// 默认国家给沙特
func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) { func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) {
type info struct { type info struct {
Name string Name string
...@@ -14,7 +16,11 @@ func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) { ...@@ -14,7 +16,11 @@ func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) {
} }
res := new(info) res := new(info)
if err := model.DB().Raw("select name, area from res_country where name = (select country from user where id = ?)", id).First(&res).Error; err != nil { if err := model.DB().Raw("select name, area from res_country where name = (select country from user where id = ?)", id).First(&res).Error; err != nil {
if err != gorm.ErrRecordNotFound {
return "", 0, myerr.WrapErr(err) return "", 0, myerr.WrapErr(err)
} }
// gorm.ErrRecordNotFound
return "KSA", 1, nil
}
return res.Name, res.Area, nil return res.Name, res.Area, nil
} }
...@@ -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)
......
...@@ -3,13 +3,17 @@ package user_m ...@@ -3,13 +3,17 @@ package user_m
import ( import (
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/myerr" "hilo-group/myerr"
"strings"
) )
type SuperManager struct { type SuperManager struct {
mysql.Entity mysql.Entity
*domain.Model `gorm:"-"` *domain.Model `gorm:"-"`
UserId mysql.ID UserId mysql.ID
IsAll bool
Countries string
} }
func IsSuperManager(model *domain.Model, userId mysql.ID) (bool, error) { func IsSuperManager(model *domain.Model, userId mysql.ID) (bool, error) {
...@@ -22,6 +26,33 @@ func IsSuperManager(model *domain.Model, userId mysql.ID) (bool, error) { ...@@ -22,6 +26,33 @@ func IsSuperManager(model *domain.Model, userId mysql.ID) (bool, error) {
return n > 0, nil return n > 0, nil
} }
// 对某人是否有超管权限
func IsSuperManagerV2(model *domain.Model, userId, targetUserId mysql.ID) (bool, error) {
var man SuperManager
if err := model.Db.Model(&SuperManager{}).Where(&SuperManager{
UserId: userId,
}).First(&man).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("IsSuperManagerV2 fail:%v", err)
}
return false, nil
}
if man.IsAll {
return true, nil
}
targetUser, err := GetUser(model, targetUserId)
if err != nil {
return false, err
}
countries := strings.Split(man.Countries, ",")
for _, c := range countries {
if c == targetUser.Country {
return true, nil
}
}
return false, nil
}
func GetSuperManagerAll(model *domain.Model) ([]uint64, error) { func GetSuperManagerAll(model *domain.Model) ([]uint64, error) {
superManagers := []SuperManager{} superManagers := []SuperManager{}
if err := model.Db.Model(&SuperManager{}).Find(&superManagers).Error; err != nil { if err := model.Db.Model(&SuperManager{}).Find(&superManagers).Error; err != nil {
......
...@@ -85,12 +85,29 @@ func GetUsersByIds(model *domain.Model, userIds []mysql.ID) ([]User, error) { ...@@ -85,12 +85,29 @@ func GetUsersByIds(model *domain.Model, userIds []mysql.ID) ([]User, error) {
return users, nil return users, nil
} }
// 分批获取userIds
func GetUserMapByIds(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]User, error) { func GetUserMapByIds(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]User, error) {
rows, err := GetUsersByIds(model, userIds) result := make(map[mysql.ID]User, 0)
end := 500
if end > len(userIds) {
end = len(userIds)
}
var rows []User
start := 0
for start < len(userIds) {
tmp, err := GetUsersByIds(model, userIds[start:end])
if err != nil { if err != nil {
return nil, err return result, err
} else {
rows = append(rows, tmp...)
}
start += 500
end += 500
if end > len(userIds) {
end = len(userIds)
}
//model.Log.Infof("GetUserMapByIds start:%v-end:%v", start, end)
} }
result := make(map[mysql.ID]User, 0)
for _, i := range rows { for _, i := range rows {
result[i.ID] = i result[i.ID] = i
} }
...@@ -127,3 +144,39 @@ func GetUsers(model *domain.Model, ids []mysql.ID) ([]*User, error) { ...@@ -127,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
}
...@@ -59,14 +59,34 @@ func GetVip(db *gorm.DB, userId uint64) (*UserVip, error) { ...@@ -59,14 +59,34 @@ func GetVip(db *gorm.DB, userId uint64) (*UserVip, error) {
return nil, nil return nil, nil
} }
// 分批获取
func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) { func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) {
result := make(map[uint64]*int64, 0)
rows := make([]UserVip, 0) rows := make([]UserVip, 0)
err := mysql.Db.Where("user_id IN ?", userIds).Find(&rows).Error end := 500
if end > len(userIds) {
end = len(userIds)
}
start := 0
for start < len(userIds) {
tmp := make([]UserVip, 0)
err := mysql.Db.Where("user_id IN ?", userIds[start:end]).Find(&tmp).Error
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err != nil {
return result, err
} else {
rows = append(rows, tmp...)
}
start += 500
end += 500
if end > len(userIds) {
end = len(userIds)
}
//mylogrus.MyLog.Infof("BatchGetVips start:%v-end:%v", start, end)
}
result := make(map[uint64]*int64, 0)
for _, i := range userIds { for _, i := range userIds {
result[i] = nil result[i] = nil
} }
......
...@@ -6,22 +6,18 @@ import ( ...@@ -6,22 +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/event/gift_ev" "hilo-group/domain/cache/group_c"
"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"
...@@ -33,8 +29,8 @@ func EventInit() { ...@@ -33,8 +29,8 @@ func EventInit() {
GroupEvents() GroupEvents()
GroupImMass() GroupImMass()
GroupTheme() GroupTheme()
SendGift() // 送礼事件 //SendGift() // 送礼事件
OnMic() // 在麦上事件 GroupInMicChangeEvent() // 用户进房推送mic位置信息
} }
func GroupSupportEvents() { func GroupSupportEvents() {
...@@ -246,6 +242,7 @@ func GroupEvents() { ...@@ -246,6 +242,7 @@ func GroupEvents() {
} }
err := uer.Save(model.Db) err := uer.Save(model.Db)
model.Log.Infof("AddGroupInAsync, UserEnterRoom err: %v", err) model.Log.Infof("AddGroupInAsync, UserEnterRoom err: %v", err)
group_c.ZAddUserEnterRoom(model, event.UserId, event.GroupId) // redis存储
return err return err
}) })
...@@ -468,93 +465,69 @@ func FlushHiloInfo(extId string, isVip bool, isPrettyCode bool, medals []uint32, ...@@ -468,93 +465,69 @@ func FlushHiloInfo(extId string, isVip bool, isPrettyCode bool, medals []uint32,
func SendGift() { func SendGift() {
// 送礼事件-势力经验 // 送礼事件-势力经验
gift_ev.AddSendGiftEventSync(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)
exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId) // if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
if err != nil { // return nil
model.Log.Infof("CheckGroupPowerUser fail %+v", err) // }
return err // exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId)
} // if err != nil {
if exist { // model.Log.Infof("CheckGroupPowerUser fail %+v", err)
exp := sendGiftEvent.GiftN * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) * sendGiftEvent.ResGift.DiamondNum // return err
return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼") // }
} // if exist {
return nil // 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, "送礼")
// }
// 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
} // }
var userIds = []mysql.ID{sendGiftEvent.SendUserId} // if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
userIds = append(userIds, sendGiftEvent.ReceiveUserIds...) // return nil
groupPowers, err := groupPower_m.BatchGetGroupPowerUser(model, userIds) // }
if err != nil { // var userIds = []mysql.ID{sendGiftEvent.SendUserId}
model.Log.Errorf("AddSendGiftEventAsync fail:%v", err) // userIds = append(userIds, sendGiftEvent.ReceiveUserIds...)
return err // groupPowers, err := groupPower_m.BatchGetGroupPowerUser(model, userIds)
} // if err != nil {
// 送礼加分 // model.Log.Errorf("AddSendGiftEventAsync fail:%v", err)
if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok { // return err
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 { // // 送礼加分
model.Log.Errorf("IncrGroupPowerMonthStarScore famous fail:%v", err) // if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok {
} // diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds))
if err := groupPower_m.IncrGroupPowerDayStarScore(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("IncrGroupPowerDayStarScore 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 {
// 收礼加分 // 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_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeCharm, diamonds, 0); err != nil { // for _, userId := range sendGiftEvent.ReceiveUserIds {
model.Log.Errorf("IncrGroupPowerMonthStarScore charm fail:%v", err) // if data, ok := groupPowers[userId]; ok {
} // diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum
if err := groupPower_m.IncrGroupPowerDayStarScore(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("IncrGroupPowerDayStarScore 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 {
} // 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
}
...@@ -6,12 +6,16 @@ import ( ...@@ -6,12 +6,16 @@ import (
"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/redisCli" "git.hilo.cn/hilo-common/resource/redisCli"
"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"
"hilo-group/domain/model/user_m"
"hilo-group/domain/service/signal_s" "hilo-group/domain/service/signal_s"
"hilo-group/myerr" "hilo-group/myerr"
"hilo-group/myerr/bizerr" "hilo-group/myerr/bizerr"
...@@ -315,16 +319,115 @@ func (s *GroupMicService) IncrGroupPowerOnMicExpAndTime(groupId string, userId u ...@@ -315,16 +319,115 @@ 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
} }
// 检查cp上麦
func (s *GroupMicService) CheckCpOnMic(groupUuid string) {
model := domain.CreateModelContext(s.svc.MyContext)
// 填充cp麦位
micNumType, err := group_m.GetMicNumType(model, groupUuid)
if err != nil {
return
}
_, micUsers, err := group_m.GetAllMic(groupUuid, micNumType)
if err != nil {
return
}
// userId->micIndex
var userMicIndex = make(map[uint64]int)
var userIds []uint64
forbidMap := make(map[uint64]bool)
for _, u := range micUsers {
userMicIndex[u.UserId] = u.I
userIds = append(userIds, u.UserId)
forbidMap[u.UserId] = u.Forbid
}
cpPairs, err := rpc.MGetUserCpPairs(model, userIds)
// 更新麦上cp的信息
if err != nil {
model.Log.Errorf("MGetUserCpPairs fail:%v", err)
return
}
users, err := user_m.GetUserMapByIds(model, userIds)
if err != nil {
model.Log.Errorf("GetUserMapByIds fail:%v", err)
return
}
for _, pairs := range cpPairs {
level := pairs[2]
if level < 5 { // cpLevel < 5 级别没有麦位特效
continue
}
userId := pairs[0]
cpUserId := pairs[1]
redisLock(redis_key.GetPrefixGroupMicUserInLock(userId), uuid.NewV4().String(), time.Second*2, func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
mic, err := group_m.GetMic(model, groupUuid, userMicIndex[userId])
if err != nil {
return err
}
return mic.Update(userId, users[userId].ExternalId, cpUserId, forbidMap[userId])
})
redisLock(redis_key.GetPrefixGroupMicUserInLock(cpUserId), uuid.NewV4().String(), time.Second*2, func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
mic, err := group_m.GetMic(model, groupUuid, userMicIndex[cpUserId])
if err != nil {
return err
}
return mic.Update(cpUserId, users[cpUserId].ExternalId, userId, forbidMap[cpUserId])
})
}
return
}
// 检查cp下麦
func (s *GroupMicService) CheckCpLeaveMic(groupUuid string, leaveUid uint64) {
model := domain.CreateModelContext(s.svc.MyContext)
// 填充cp麦位
micNumType, err := group_m.GetMicNumType(model, groupUuid)
if err != nil {
return
}
_, micUsers, err := group_m.GetAllMic(groupUuid, micNumType)
if err != nil {
return
}
// userId->micIndex
var userMicIndex = make(map[uint64]int)
var cpUserId uint64
forbidMap := make(map[uint64]bool)
for _, u := range micUsers {
if u.UserId == leaveUid {
cpUserId = u.CpUserId
}
userMicIndex[u.UserId] = u.I
forbidMap[u.UserId] = u.Forbid
}
if cpUserId <= 0 {
return
}
user, err := user_m.GetUser(model, cpUserId)
if err != nil {
model.Log.Errorf("GetUser fail:%v", err)
return
}
redisLock(redis_key.GetPrefixGroupMicUserInLock(cpUserId), uuid.NewV4().String(), time.Second*2, func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
mic, err := group_m.GetMic(model, groupUuid, userMicIndex[cpUserId])
if err != nil {
return err
}
return mic.Update(cpUserId, user.ExternalId, 0, forbidMap[cpUserId])
})
return
}
...@@ -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
}
This diff is collapsed.
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
......
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.
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.
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.