Commit dd469dc1 authored by chenweijian's avatar chenweijian Committed by hujiebin

Fix/group support

parent 2cc919d6
......@@ -18,6 +18,8 @@ func Init() {
group_cron.GroupPowerExpClear() // 清理家族经验/等级
group_cron.GroupPowerMonthRankAct()
//group_cron.GroupInEventInit() // 进房事件
group_cron.GroupPowerGradeExp() // 家族升级(上麦事件会用到) todo
group_cron.CreateGroup() //
group_cron.GroupPowerGradeExp() // 家族升级(上麦事件会用到) todo
group_cron.CreateGroup() //
group_cron.CalcGroupSupport() // 群组扶持计算
group_cron.CalcGroupSupport_OldData() // 群组扶持计算-旧数据
}
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/event/gift_ev"
"hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m"
"time"
)
// 送礼事件
......@@ -18,8 +24,9 @@ func SendGiftEvent() {
for true {
model := domain.CreateModelNil()
if sendGiftEvent := gift_c.BLPopQueueSendGift(model); sendGiftEvent != nil {
groupPowerGrade(model, sendGiftEvent) // 家族经验
groupPowerStar(model, sendGiftEvent) // 家族之星
groupPowerGrade(model, sendGiftEvent) // 家族经验
groupPowerStar(model, sendGiftEvent) // 家族之星
groupSupportAddConsume(model, sendGiftEvent) // 群组扶持
}
}
}()
......@@ -88,3 +95,40 @@ func groupPowerStar(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
}
return
}
// 群组扶持增加流水数据
func groupSupportAddConsume(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
if time.Now().Unix() <= 1692843600 {
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
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
}
......@@ -2,12 +2,16 @@ package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-group/domain/service/group_power_s"
)
// 家族贡献月度排行榜发奖
func GroupPowerMonthRankAct() {
if !config.IsMaster() {
return
}
c := cron.New()
// 每月1号0:01结算发奖
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 30 10 24 8 ?"
_ = c.AddFunc(spec, func() {
defer utils.CheckGoPanic()
var model = domain.CreateModelNil()
//开始
model.Log.Infof("CalcGroupSupport_OldData start")
beginTime, _, period := group_m.GetSupportLevelTime(time.Now())
endTime := time.Unix(1692843600, 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(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()
}
......@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS]
REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT]
SECRET=hilo1632
ISSUER_API=hiloApi
......
......@@ -182,6 +182,17 @@ func (g *GiftOperate) BatchGetConsumeByRange(beginTime, endTime time.Time) ([]Sc
return rows, nil
}
func (g *GiftOperate) BatchGetSupportList(beginTime, endTime time.Time) ([]uint64, error) {
userIds := make([]uint64, 0)
err := g.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) {
type Result struct {
N uint32
......
package group_s
import (
"context"
"git.hilo.cn/hilo-common/_const/enum/msg_e"
"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"
"github.com/go-redis/redis/v8"
"hilo-group/_const/enum/gift_e"
"hilo-group/domain/event/group_ev"
"hilo-group/domain/model/gift_m"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/msg_m"
"hilo-group/domain/model/res_m"
"hilo-group/domain/model/user_m"
"hilo-group/myerr/bizerr"
"strconv"
"time"
)
......@@ -173,3 +181,128 @@ func (s *GroupService) RenewGroupSupporter(groupId string, userIds []uint64) err
return nil
})
}
func (s *GroupService) GroupSupportResult(time time.Time) error {
model := domain.CreateModelContext(s.svc.MyContext)
_, _, period := group_m.GetSupportLevelTime(time)
// 群组扶持数值
groupGradeMap, err := getGroupGradeMap(model, period)
if err != nil {
model.Log.Errorf("GroupSupportResult time:%v, err:%v", time, err)
return err
}
model.Log.Infof("GroupSupportResult period:%s, len:%d, groupUidGadeMap:%v", period, len(groupGradeMap), groupGradeMap)
// 房间访问人数
roomVisitCount, err := GetAllRoomNonZeroVisitCount()
if err != nil {
model.Log.Errorf("GroupSupportResult err:%v", err)
return err
}
// 入库群组扶持结果
for g, grade := range groupGradeMap {
r := group_m.InitGroupSupportResult(model, g, grade, period, roomVisitCount[g])
r.SetOnDuplicateKeyIGNORE()
if err = r.Persistent(); err != nil {
model.Log.Errorf("GroupSupportResult InitGroupSupportResult r:%+v, err:%v", r, err)
}
}
// 小助手通知
AssistantNotification(model, groupGradeMap)
return nil
}
func getGroupGradeMap(model *domain.Model, period string) (map[string]uint8, error) {
// 配置
gsConfig, err := res_m.GetResGroupSupportByValid(model)
if err != nil {
model.Log.Errorf("GroupSupportResult err:%v", err)
return nil, err
}
// 群组扶持数值
groupGradeMap := make(map[string]uint8, 0)
//userNum := make(map[string]uint32, 0)
// 流水
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
var start int64
count := int64(999)
var zList []redis.Z
// 一次取1000个处理
for start == 0 || len(zList) > 0 {
stop := start + count
zList, err = model.RedisCluster.ZRangeWithScores(context.Background(), keyDiamond, start, stop).Result()
if err != nil {
model.Log.Errorf("GroupSupportResult err:%v", err)
return nil, err
}
if len(zList) == 0 {
break
}
for _, v := range zList {
imGroupId := v.Member.(string)
consume := mysql.Num(v.Score)
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, imGroupId)
supportNum, err := model.RedisCluster.SCard(context.Background(), keySupportNum).Result()
if err != nil {
model.Log.Errorf("GroupSupportResult key:%s, err:%v", keySupportNum, err)
return nil, err
}
for j := len(gsConfig) - 1; j >= 0; j-- {
if mysql.Num(supportNum) >= gsConfig[j].ContributeUserNum && consume >= gsConfig[j].ContributeDiamondNum {
groupGradeMap[imGroupId] = gsConfig[j].Grade
//userNum[imGroupId] = uint32(supportNum)
break
}
}
}
start = stop + 1
}
return groupGradeMap, nil
}
func AssistantNotification(model *domain.Model, groupGradeMap map[string]uint8) {
// 小助手通知
for g, _ := range groupGradeMap {
userId, err := group_m.GetProfitAllocator(model, g)
if err != nil {
model.Log.Errorf("GroupSupportResult msg GetProfitAllocator err:%v, groupUid:%v", err, g)
continue
}
//推送
user, err := user_m.GetUser(model, userId)
if err != nil {
model.Log.Infof("GroupSupportResult msg GetUser userId:=%v, err:=%v", userId, err)
continue
}
record := msg_m.NewUserRecord(model, user.ID, msg_e.GroupSupportResult, "", 0, "", "", "", "", "")
if err := record.Persistent(); err != nil {
model.Log.Infof("GroupSupportResult msg record.Persistent() err:%v", err)
continue
}
msg_m.SendEmasMsgAssistant(model, user.ExternalId, user.DeviceType)
}
}
func GetAllRoomNonZeroVisitCount() (map[string]uint, error) {
m, err := GetAllRoomVisitCount()
if err != nil {
return nil, err
}
result := make(map[string]uint, 0)
for g, s := range m {
if c, err := strconv.Atoi(s); err == nil && c > 0 {
result[g] = uint(c)
}
}
return result, nil
}
func GetAllRoomVisitCount() (map[string]string, error) {
key := rediskey.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HGetAll(context.Background(), key).Result()
}
......@@ -3,6 +3,7 @@ package main
import (
"fmt"
"git.hilo.cn/hilo-common/resource/consul"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-group/cron"
"hilo-group/domain/service/event_s"
"hilo-group/route"
......@@ -17,6 +18,7 @@ const (
func main() {
cron.Init() // 开启定时任务
event_s.EventInit() // 注册事件(内部事件+mysql拟kafka)
redisCli.InitCluster() // redis集群
r := route.InitRouter() // 注册路由
consul.RegisterToConsul(PORT, RegisterName, RegisterTag) // 服务注册
r.Run(fmt.Sprintf(":%d", PORT)) // 启动服务
......
......@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS]
REDIS_HOST=r-eb3btxn8vfdsuwdbuf.redis.dubai.rds.aliyuncs.com:6379
REDIS_PASSWORD=
REDIS_CLUSTER_HOST=r-eb3yt6k8zgxs62kjjs.redis.dubai.rds.aliyuncs.com:6379
REDIS_CLUSTER_PASSWORD=
[JWT]
SECRET=hilo1504
ISSUER_API=hiloApi
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment