history.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. package handler
  2. import (
  3. "bet24.com/log"
  4. "bet24.com/redis"
  5. pb "bet24.com/servers/micros/privateroom/proto"
  6. "encoding/json"
  7. "sort"
  8. "strconv"
  9. "sync"
  10. "time"
  11. )
  12. const max_history_sec = 86400 // 最多存储时长
  13. const refresh_config_sec = 600
  14. func getRedisKey() string {
  15. return "privateroom:history"
  16. }
  17. type historyItem struct {
  18. pb.RoomInfoBrief
  19. Owner int
  20. StartTime string
  21. RoomType string
  22. Winners []int
  23. HistoryTime int64
  24. EndType string
  25. }
  26. func (hi *historyItem) isUserRelated(userId int) bool {
  27. if hi.Owner == userId {
  28. return true
  29. }
  30. for _, v := range hi.UserList {
  31. if v == nil {
  32. continue
  33. }
  34. if v.UserId == userId {
  35. return true
  36. }
  37. }
  38. return false
  39. }
  40. func (h *historyItem) dump(detail bool) {
  41. log.Release(" RoomNo:%d Creator:%d GameId:%d Rule:%s EndType[%s]", h.RoomNo, h.Owner, h.GameId, h.RuleName, h.EndType)
  42. if !detail {
  43. return
  44. }
  45. for _, v := range h.UserList {
  46. if v == nil {
  47. continue
  48. }
  49. log.Release(" User[%d] Score[%d]", v.UserId, v.Score)
  50. }
  51. }
  52. type historyMgr struct {
  53. isDirty bool
  54. lock *sync.RWMutex
  55. histories []historyItem
  56. }
  57. var historymgr *historyMgr
  58. func getHistoryManager() *historyMgr {
  59. if historymgr == nil {
  60. historymgr = new(historyMgr)
  61. }
  62. return historymgr
  63. }
  64. func (m *historyMgr) run() {
  65. log.Release("privateroom.historymgr.run()")
  66. m.lock = &sync.RWMutex{}
  67. m.loadHistoryFromRedis()
  68. m.flush()
  69. }
  70. func (m *historyMgr) loadHistoryFromRedis() {
  71. data, ok := redis.String_Get(getRedisKey())
  72. if data == "" || !ok {
  73. return
  74. }
  75. m.lock.Lock()
  76. err := json.Unmarshal([]byte(data), &m.histories)
  77. m.lock.Unlock()
  78. if err != nil {
  79. log.Release("privateroom.historyMgr.loadHistoryFromRedis Unmarshal failed err:%v,%s", err, data)
  80. return
  81. }
  82. }
  83. func (m *historyMgr) addHistory(item roomInfo, endType string) {
  84. hi := historyItem{
  85. RoomInfoBrief: *item.ToBrief(),
  86. StartTime: item.StartTime,
  87. RoomType: item.RoomType,
  88. EndType: endType,
  89. HistoryTime: time.Now().Unix(),
  90. }
  91. if len(item.Winners) > 0 {
  92. hi.Winners = make([]int, len(item.Winners))
  93. copy(hi.Winners, item.Winners)
  94. }
  95. m.lock.Lock()
  96. m.isDirty = true
  97. m.histories = append(m.histories, hi)
  98. m.lock.Unlock()
  99. go writeRoomRecordToDB(&item)
  100. }
  101. func (m *historyMgr) checkTimeout() {
  102. now := time.Now().Unix()
  103. removeIndex := 0
  104. m.lock.RLock()
  105. for i := 0; i < len(m.histories); i++ {
  106. removeIndex = i
  107. if now-m.histories[i].HistoryTime < max_history_sec {
  108. break
  109. }
  110. }
  111. m.lock.RUnlock()
  112. if removeIndex == 0 {
  113. return
  114. }
  115. log.Release("privateroom.historymgr.checkTimeout removeIndex = %d", removeIndex)
  116. m.lock.Lock()
  117. m.isDirty = true
  118. m.histories = m.histories[removeIndex:]
  119. m.lock.Unlock()
  120. }
  121. func (m *historyMgr) forceFlush() {
  122. m.isDirty = true
  123. m.doFlush()
  124. }
  125. func (m *historyMgr) flush() {
  126. time.AfterFunc(refresh_config_sec*time.Second, m.flush)
  127. m.checkTimeout()
  128. if !m.isDirty {
  129. return
  130. }
  131. m.doFlush()
  132. }
  133. func (m *historyMgr) doFlush() {
  134. m.lock.RLock()
  135. m.isDirty = false
  136. d, _ := json.Marshal(m.histories)
  137. m.lock.RUnlock()
  138. go redis.String_Set(getRedisKey(), string(d))
  139. }
  140. func (m *historyMgr) dump(param string) {
  141. log.Release("-------------------------------")
  142. log.Release("historyMgr.historyMgr.dump %s", param)
  143. defer func() {
  144. log.Release("+++++++++++++++++++++++++++++++")
  145. log.Release("")
  146. }()
  147. if param == "" {
  148. m.lock.RLock()
  149. for _, v := range m.histories {
  150. v.dump(false)
  151. }
  152. m.lock.RUnlock()
  153. return
  154. }
  155. roomNo, err := strconv.Atoi(param)
  156. if err != nil {
  157. log.Release("invalid param %s", param)
  158. return
  159. }
  160. m.lock.RLock()
  161. for _, v := range m.histories {
  162. if v.RoomNo != roomNo {
  163. continue
  164. }
  165. v.dump(true)
  166. }
  167. m.lock.RUnlock()
  168. }
  169. func (m *historyMgr) getHistory(userId int) string {
  170. var ret []historyItem
  171. m.lock.RLock()
  172. for _, v := range m.histories {
  173. if v.isUserRelated(userId) {
  174. ret = append(ret, v)
  175. }
  176. }
  177. m.lock.RUnlock()
  178. sort.Slice(ret, func(i, j int) bool {
  179. return ret[i].HistoryTime > ret[j].HistoryTime
  180. })
  181. d, _ := json.Marshal(ret)
  182. return string(d)
  183. }