package userinfo import ( "encoding/json" "os" "strconv" "sync" "time" "bet24.com/log" audioroomPb "bet24.com/servers/micros/audioroom/proto" item "bet24.com/servers/micros/item_inventory/proto" notification "bet24.com/servers/micros/notification/proto" platformconfig "bet24.com/servers/micros/platformconfig/proto" pb "bet24.com/servers/micros/userservices/proto" ) const config_key = "switchlevel_config" type usermgr struct { lock *sync.RWMutex userlist map[int]*userInfo SwitchLevelLists []pb.SwitchLevel } func newUserMgr() *usermgr { obj := new(usermgr) obj.lock = &sync.RWMutex{} obj.userlist = make(map[int]*userInfo) obj.checkTimeout() obj.loadConfig() return obj } func (this *usermgr) loadConfig() { go time.AfterFunc(5*time.Minute, this.loadConfig) if data := platformconfig.GetConfig(config_key); data != "" { if err := json.Unmarshal([]byte(data), &this.SwitchLevelLists); err == nil { return } return } data, err := os.ReadFile("serviceconf/switchlevel_config.json") if err != nil { log.Release("read config failed serviceconf/switchlevel_config.json %v", err) } if err = json.Unmarshal(data, &this.SwitchLevelLists); err == nil { platformconfig.SetConfig(config_key, string(data)) return } log.Release("Unmarshal config [%s] err:%v", string(data), err) } func (this *usermgr) getInfo(userId int) *pb.UserHotInfo { u := this.getUserInfo(userId) if u == nil { u = newUserHotInfo(userId) if u == nil { return nil } this.lock.Lock() this.userlist[userId] = u this.lock.Unlock() } else { u.updateTick() } return &u.UserHotInfo } func (this *usermgr) getUserInfoInBulk(userIds []int) []pb.UserHotInfo { var ret []pb.UserHotInfo for _, v := range userIds { ui := this.getInfo(v) if ui != nil { ret = append(ret, *ui) } } return ret } func (this *usermgr) getUserInfo(userId int) *userInfo { this.lock.RLock() ret, ok := this.userlist[userId] this.lock.RUnlock() if !ok { return nil } return ret } func (this *usermgr) checkTimeout() { time.AfterFunc(60*time.Second, this.checkTimeout) var toRemove []int this.lock.RLock() for _, v := range this.userlist { if v.isTimeout() { toRemove = append(toRemove, v.UserId) } } this.lock.RUnlock() if len(toRemove) == 0 { return } log.Release("userinfo.remove timeout users %v", toRemove) this.lock.Lock() for _, v := range toRemove { delete(this.userlist, v) } this.lock.Unlock() } func (this *usermgr) clear(userId int) { this.lock.Lock() defer this.lock.Unlock() delete(this.userlist, userId) } // 保存国家地区 func (this *usermgr) saveCountry(userId int, countryName, currency string) int { currency = "SAR" usr := this.getInfo(userId) if usr == nil { return 11 } usr.Currency = currency return saveCountry(userId, countryName, currency, 1) } // 锁定国家地区 func (this *usermgr) lockCountry(userId int, currency string) int { currency = "SAR" usr := this.getInfo(userId) if usr == nil { return 11 } usr.Currency = currency return saveCountry(userId, "SA", currency, 0) } func (this *usermgr) setUserDecoration(userId int, decorationType int, itemId int) bool { if itemId > 0 && !item.CheckDecortaionType(decorationType, itemId, userId) { log.Release("usermgr.setUserDecoration CheckDecortaionType failed[%d,%d]", decorationType, itemId) return false } usr := this.getInfo(userId) if usr == nil { return false } // 设置内容 found := false for k, v := range usr.Decorations { if v.Type == decorationType { found = true if itemId == 0 { usr.Decorations = append(usr.Decorations[:k], usr.Decorations[k+1:]...) } else { usr.Decorations[k].ItemId = itemId } break } } if !found && itemId == 0 { log.Release("usermgr.setUserDecoration !found && itemId == 0 [%d,%d]", decorationType, itemId) return false } if !found { usr.Decorations = append(usr.Decorations, pb.UserDecoration{Type: decorationType, ItemId: itemId}) } // 写入数据库 saveDecorations(userId, decorationType, itemId) switch decorationType { case item.Item_Decoration_AudioRoomDataCard: // 3=语聊房资料卡 fallthrough case item.Item_Decoration_AudioRoomBackground: // 4=语聊房背景 audioroomPb.OnAudioRoomMsg(userId, "NotifyRoom", "") } // 发通知给客户端 this.sendUserDecorationNotify(usr) return true } func (this *usermgr) sendUserDecorationNotify(usr *pb.UserHotInfo) { var decorations struct { Decorations []pb.UserDecoration } decorations.Decorations = usr.Decorations d, _ := json.Marshal(decorations) log.Debug("usermsg.sendUserDecorationNotify %d %s", usr.UserId, string(d)) notification.AddNotification(usr.UserId, notification.Notification_UserInfoChanged, string(d)) } func (this *usermgr) onDecorationExpired(userId int, itemId int) { usr := this.getInfo(userId) if usr == nil { return } for i := 0; i < len(usr.Decorations); { if usr.Decorations[i].ItemId == itemId { saveDecorations(userId, usr.Decorations[i].Type, 0) usr.Decorations = append(usr.Decorations[:i], usr.Decorations[i+1:]...) this.sendUserDecorationNotify(usr) return } else { i++ } } } func (this *usermgr) changeSwitchStatus(userId int, switchType string, switchStatus int) { usr := this.getInfo(userId) if usr == nil { log.Release("usermgr.changeSwitchStatus The user does not exist. userId=%d", userId) return } isNew := true log.Release("userId:%d, changeSwitchStatus:%s", userId, switchType) for i := 0; i < len(usr.Switches); i++ { if usr.Switches[i].SwitchType != switchType { continue } isNew = false usr.Switches[i].SwitchStatus = switchStatus break } // 新增 if isNew { usr.Switches = append(usr.Switches, pb.SwitchInfo{ SwitchType: switchType, SwitchStatus: switchStatus, }) } go func() { //d, _ := json.Marshal(usr.Switches) //notification.AddNotification(userId, notification.Notification_UserInfoChanged, string(d)) // 存储到数据库 changeSwitchStatus(userId, switchType, switchStatus) }() return } func (this *usermgr) getSwitchLevelInfo() []pb.SwitchLevel { return this.SwitchLevelLists } func (this *usermgr) addUserCharm(userId int, charm int) { if charm < 0 { log.Release("usermgr.addUserCharm charm=%d", charm) return } usr := this.getInfo(userId) if usr == nil { log.Release("usermgr.addUserCharm The user does not exist. userId=%d", userId) return } log.Debug("usermgr.addUserCharm %d %d", userId, charm) usr.Charm += charm var charmNoti struct { Charm int } charmNoti.Charm = usr.Charm d, _ := json.Marshal(charmNoti) notification.AddNotification(userId, notification.Notification_UserInfoChanged, string(d)) go updateUserCharm(userId, usr.Charm) } func (this *usermgr) dumpUser(param string) { log.Release("-------------------------------") log.Release("usermgr.dumpUser %s", param) defer func() { log.Release("+++++++++++++++++++++++++++++++") log.Release("") }() var userId int var err error userId, err = strconv.Atoi(param) if err == nil { uv := this.getUserInfo(userId) if uv == nil { log.Release("user %d not exist", userId) return } uv.dump() return } this.lock.RLock() for _, v := range this.userlist { v.dump() } log.Release("%v", this.SwitchLevelLists) this.lock.RUnlock() }