package combomatch import ( "bet24.com/log" "bet24.com/redis" "encoding/json" "strconv" "sync" "time" ) const max_history_sec = 86400 * 3 // 最多存储时长 const refresh_history_config_sec = 600 func getRedisKey() string { return "combomatch:history" } type historyMgr struct { isDirty bool lock *sync.RWMutex histories []combohistory } var hm *historyMgr func getHistoryManager() *historyMgr { if hm == nil { hm = new(historyMgr) hm.lock = &sync.RWMutex{} } return hm } func (hm *historyMgr) run() { hm.loadHistoryFromRedis() hm.flush() } func (m *historyMgr) loadHistoryFromRedis() { data, ok := redis.String_Get(getRedisKey()) if data == "" || !ok { return } m.lock.Lock() err := json.Unmarshal([]byte(data), &m.histories) m.lock.Unlock() if err != nil { log.Release("combomatch.historyMgr.loadHistoryFromRedis Unmarshal failed err:%v,%s", err, data) return } } func (m *historyMgr) checkTimeout() { now := time.Now().Unix() removeIndex := 0 m.lock.RLock() for i := 0; i < len(m.histories); i++ { removeIndex = i if now-m.histories[i].EndTime < max_history_sec { break } } m.lock.RUnlock() if removeIndex == 0 { return } log.Release("combomatch.historymgr.checkTimeout removeIndex = %d", removeIndex) m.lock.Lock() m.isDirty = true m.histories = m.histories[removeIndex:] m.lock.Unlock() } func (m *historyMgr) forceFlush() { m.isDirty = true m.doFlush() } func (m *historyMgr) flush() { time.AfterFunc(refresh_history_config_sec*time.Second, m.flush) m.checkTimeout() if !m.isDirty { return } m.doFlush() } func (m *historyMgr) doFlush() { m.lock.RLock() m.isDirty = false d, _ := json.Marshal(m.histories) m.lock.RUnlock() go redis.String_Set(getRedisKey(), string(d)) } func (hm *historyMgr) dump(param2 string) { log.Release("-------------------------------") log.Release("combomatch.historyMgr.dump[%s]", param2) defer func() { log.Release("+++++++++++++++++++++++++++++++") log.Release("") }() if param2 == "" { hm.lock.RLock() for _, v := range hm.histories { v.dump(false) } hm.lock.RUnlock() return } matchId, err := strconv.Atoi(param2) if err != nil { log.Release(" atoi error %v", err) return } hm.lock.RLock() for _, v := range hm.histories { if v.MatchId == matchId { v.dump(true) } } hm.lock.RUnlock() } func (hm *historyMgr) getHistory(userId int) string { var ret []combohistory hm.lock.RLock() for _, v := range hm.histories { if v.isUserEnrolled(userId) { ret = append(ret, v) } } hm.lock.RUnlock() d, _ := json.Marshal(ret) return string(d) } func (hm *historyMgr) addHistory(h combohistory) { hm.lock.Lock() hm.histories = append(hm.histories, h) hm.isDirty = true hm.lock.Unlock() }