read.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package readcache
  2. import (
  3. "fmt"
  4. "leafstalk/covenant/monitor"
  5. "leafstalk/module"
  6. "leafstalk/otherutils"
  7. "reflect"
  8. "strconv"
  9. "time"
  10. cach2 "github.com/patrickmn/go-cache"
  11. )
  12. type SameStructCache struct {
  13. Name string
  14. AllPlayers *cach2.Cache
  15. tokens otherutils.RoutineTokens
  16. loadFilter otherutils.FilterInt64
  17. skeleton *module.Skeleton
  18. Load func(id int64) (interface{}, error)
  19. New func(playerId int64) interface{}
  20. PrePocess func(interface{})
  21. }
  22. func NewCache(skeleton *module.Skeleton) *SameStructCache {
  23. c := new(SameStructCache)
  24. c.skeleton = skeleton
  25. return c
  26. }
  27. type callBackFun struct {
  28. fprocess func(p interface{})
  29. fErrProcess func(playerId int64, errorCode int)
  30. }
  31. func (c *SameStructCache) Init(load func(id int64) (interface{}, error), newObj func(playerId int64) interface{}, preProcess func(interface{})) {
  32. c.AllPlayers = cach2.New(5*time.Minute, 10*time.Minute)
  33. c.tokens.Init(10)
  34. c.Load = load
  35. c.New = newObj
  36. c.PrePocess = preProcess
  37. }
  38. func (c *SameStructCache) GetCacheData(playerID int64) interface{} {
  39. k := strconv.FormatInt(playerID, 10)
  40. if v, ok := c.AllPlayers.Get(k); ok {
  41. return v
  42. }
  43. return nil
  44. }
  45. func (c *SameStructCache) SetCacheData(playerID int64, v interface{}) {
  46. k2 := strconv.FormatInt(playerID, 10)
  47. c.AllPlayers.SetDefault(k2, v)
  48. }
  49. func (c *SameStructCache) LoadAndProcess(playerId int64, fprocess func(p interface{}), fErrProcess func(playerId int64, errorCode int)) {
  50. st := time.Now()
  51. //找到玩家
  52. p := c.GetCacheData(playerId)
  53. if p != nil {
  54. c.SetCacheData(playerId, p)
  55. c.PrePocess(p)
  56. fprocess(p)
  57. monitor.GoLoadTimeoutWarn(fmt.Sprintf("%s.LoadAndProcess", c.Name), playerId, st)
  58. return
  59. }
  60. //正在加载
  61. if c.loadFilter.IsExist(playerId) {
  62. t := new(callBackFun)
  63. t.fprocess = fprocess
  64. t.fErrProcess = fErrProcess
  65. c.loadFilter.AppendTask(playerId, t)
  66. return
  67. }
  68. c.loadFilter.Add(playerId)
  69. var err error
  70. c.skeleton.Go(func() {
  71. //协程加载
  72. c.tokens.Get()
  73. defer c.tokens.Release()
  74. p, err = c.Load(playerId)
  75. }, func() {
  76. defer func() {
  77. s := c.loadFilter.Remove(playerId)
  78. for _, v := range s {
  79. cft := v.(*callBackFun)
  80. if err != nil {
  81. cft.fErrProcess(playerId, 11)
  82. } else {
  83. cft.fprocess(p)
  84. }
  85. }
  86. monitor.GoLoadTimeoutWarn(fmt.Sprintf("%s.LoadAndProcess", c.Name), playerId, st)
  87. }()
  88. if err != nil {
  89. fErrProcess(playerId, 11)
  90. return
  91. }
  92. if IsNil(p) || p == nil {
  93. p = c.New(playerId)
  94. }
  95. c.SetCacheData(playerId, p)
  96. c.PrePocess(p)
  97. fprocess(p)
  98. })
  99. }
  100. func IsNil(i interface{}) bool {
  101. vi := reflect.ValueOf(i)
  102. if vi.Kind() == reflect.Ptr {
  103. return vi.IsNil()
  104. }
  105. return false
  106. }