actor.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package genPool
  2. import (
  3. "context"
  4. redisComponent "f1-game/internal/component/redis"
  5. "f1-game/internal/data"
  6. nameActor "f1-game/internal/name/actor"
  7. "fmt"
  8. cstring "github.com/cherry-game/cherry/extend/string"
  9. cfacade "github.com/cherry-game/cherry/facade"
  10. clog "github.com/cherry-game/cherry/logger"
  11. cactor "github.com/cherry-game/cherry/net/actor"
  12. cprofile "github.com/cherry-game/cherry/profile"
  13. "github.com/go-redis/redis/v8"
  14. )
  15. type (
  16. actor struct {
  17. cactor.Base
  18. nodeID string
  19. redisClient *redis.Client // redis client
  20. redisFields []string // redis查询的字段
  21. ctx context.Context // context
  22. redisKeyFormat string // redis key
  23. }
  24. )
  25. func NewActor(nodeID string) *actor {
  26. actor := &actor{
  27. nodeID: nodeID,
  28. redisFields: []string{
  29. CountKey,
  30. PeriodEndTimeKey,
  31. },
  32. ctx: context.Background(),
  33. redisKeyFormat: fmt.Sprintf("%s-gen-pool:%s:", cprofile.Env(), nodeID),
  34. }
  35. return actor
  36. }
  37. func (p *actor) AliasID() string {
  38. return nameActor.GenPool
  39. }
  40. func (p *actor) OnInit() {
  41. p.initRedis()
  42. p.loadRedisGenPoolItems()
  43. }
  44. func (p *actor) OnStop() {
  45. for _, genPoolRow := range data.GenPool.List() {
  46. genPoolItem, found := GetGenPoolItemCache(genPoolRow.ID, genPoolRow.ItemID)
  47. if !found {
  48. continue
  49. }
  50. if genPoolItem.Count == 0 && genPoolItem.PeriodEndTime == 0 {
  51. continue
  52. }
  53. p.saveGenPoolItem(genPoolItem)
  54. }
  55. }
  56. func (p *actor) OnFindChild(m *cfacade.Message) (cfacade.IActor, bool) {
  57. childID := m.TargetPath().ChildID
  58. genPoolID, ok := cstring.ToInt32(childID)
  59. if !ok {
  60. return nil, false
  61. }
  62. if !data.GenPool.ListContainID(genPoolID) {
  63. clog.Warnf("[actor] GenPoolCfg not found. genPoolID = %d", genPoolID)
  64. return nil, false
  65. }
  66. childGenPool := newActorGenPool(genPoolID)
  67. childActor, err := p.Child().Create(childID, &childGenPool)
  68. if err != nil {
  69. return nil, false
  70. }
  71. clog.Debugf("[actor] create child. actorID = %s, targetPath = %v",
  72. childActor.ActorID(),
  73. m.TargetPath(),
  74. )
  75. return childActor, true
  76. }
  77. func (p *actor) initRedis() {
  78. config := cprofile.GetConfig("gen-pool")
  79. if config.LastError() != nil {
  80. clog.Fatal("gen-pool property not exists.")
  81. return
  82. }
  83. redisID := config.GetString("redis_id")
  84. if redisID == "" {
  85. clog.Fatal("gen-pool redis_id property not exists.")
  86. return
  87. }
  88. redisConfigList := cprofile.GetConfig("redis")
  89. if redisConfigList.LastError() != nil {
  90. clog.Fatal("redis property not exists.")
  91. return
  92. }
  93. redisConfig := redisComponent.GetConfigWithRedisID(redisConfigList, redisID)
  94. if redisConfig == nil {
  95. clog.Fatalf("redis config not found. [redisID = %s]", redisID)
  96. return
  97. }
  98. _, options := redisComponent.NewClientOption(redisConfig)
  99. p.redisClient = redis.NewClient(options)
  100. }
  101. func (p *actor) buildKey(genPoolID int32, itemID int32) string {
  102. return fmt.Sprintf("%s%d:%d", p.redisKeyFormat, genPoolID, itemID)
  103. }
  104. func (p *actor) saveGenPoolItem(genPoolItem *GenPoolItem) {
  105. key := p.buildKey(genPoolItem.GenPoolID, genPoolItem.ItemID)
  106. fields := map[string]any{}
  107. fields[CountKey] = genPoolItem.Count
  108. fields[PeriodEndTimeKey] = genPoolItem.PeriodEndTime
  109. err := p.redisClient.HSet(p.ctx, key, fields).Err()
  110. if err != nil {
  111. clog.Warnf("[saveGenPoolItem] Hset error. [item = %v , err = %v]", genPoolItem, err)
  112. }
  113. }
  114. // 从redis加载产出池数据到缓存
  115. func (p *actor) loadRedisGenPoolItems() {
  116. pipeline := p.redisClient.Pipeline()
  117. defer pipeline.Close()
  118. var cmds []*redis.SliceCmd
  119. for _, genPoolRow := range data.GenPool.List() {
  120. key := p.buildKey(genPoolRow.ID, genPoolRow.ItemID)
  121. cmds = append(cmds, pipeline.HMGet(p.ctx, key, p.redisFields...))
  122. }
  123. if _, err := pipeline.Exec(p.ctx); err != nil {
  124. clog.Errorf("[LoadRedisGenPoolItems] error: %v", err)
  125. return
  126. }
  127. for i, genPoolRow := range data.GenPool.List() {
  128. result, err := cmds[i].Result()
  129. if err != nil {
  130. clog.Errorf("[LoadRedisGenPoolItems] error: %v", err)
  131. continue
  132. }
  133. genPoolItem := result2GenPoolItem(genPoolRow.ID, genPoolRow.ItemID, result)
  134. if genPoolItem.Count > 0 || genPoolItem.PeriodEndTime > 0 {
  135. SetGenPoolItemCache(genPoolItem)
  136. }
  137. }
  138. clog.Debugf("load redis genPool items. count = %d", len(cmds))
  139. }
  140. func result2GenPoolItem(genPoolID, itemID int32, result []any) *GenPoolItem {
  141. item := NewGenPoolItem(genPoolID, itemID)
  142. item.Count = cstring.ToInt64D(cstring.ToString(result[0]), 0)
  143. item.PeriodEndTime = cstring.ToInt64D(cstring.ToString(result[1]), 0)
  144. return item
  145. }