package genPool import ( "context" redisComponent "f1-game/internal/component/redis" "f1-game/internal/data" nameActor "f1-game/internal/name/actor" "fmt" cstring "github.com/cherry-game/cherry/extend/string" cfacade "github.com/cherry-game/cherry/facade" clog "github.com/cherry-game/cherry/logger" cactor "github.com/cherry-game/cherry/net/actor" cprofile "github.com/cherry-game/cherry/profile" "github.com/go-redis/redis/v8" ) type ( actor struct { cactor.Base nodeID string redisClient *redis.Client // redis client redisFields []string // redis查询的字段 ctx context.Context // context redisKeyFormat string // redis key } ) func NewActor(nodeID string) *actor { actor := &actor{ nodeID: nodeID, redisFields: []string{ CountKey, PeriodEndTimeKey, }, ctx: context.Background(), redisKeyFormat: fmt.Sprintf("%s-gen-pool:%s:", cprofile.Env(), nodeID), } return actor } func (p *actor) AliasID() string { return nameActor.GenPool } func (p *actor) OnInit() { p.initRedis() p.loadRedisGenPoolItems() } func (p *actor) OnStop() { for _, genPoolRow := range data.GenPool.List() { genPoolItem, found := GetGenPoolItemCache(genPoolRow.ID, genPoolRow.ItemID) if !found { continue } if genPoolItem.Count == 0 && genPoolItem.PeriodEndTime == 0 { continue } p.saveGenPoolItem(genPoolItem) } } func (p *actor) OnFindChild(m *cfacade.Message) (cfacade.IActor, bool) { childID := m.TargetPath().ChildID genPoolID, ok := cstring.ToInt32(childID) if !ok { return nil, false } if !data.GenPool.ListContainID(genPoolID) { clog.Warnf("[actor] GenPoolCfg not found. genPoolID = %d", genPoolID) return nil, false } childGenPool := newActorGenPool(genPoolID) childActor, err := p.Child().Create(childID, &childGenPool) if err != nil { return nil, false } clog.Debugf("[actor] create child. actorID = %s, targetPath = %v", childActor.ActorID(), m.TargetPath(), ) return childActor, true } func (p *actor) initRedis() { config := cprofile.GetConfig("gen-pool") if config.LastError() != nil { clog.Fatal("gen-pool property not exists.") return } redisID := config.GetString("redis_id") if redisID == "" { clog.Fatal("gen-pool redis_id property not exists.") return } redisConfigList := cprofile.GetConfig("redis") if redisConfigList.LastError() != nil { clog.Fatal("redis property not exists.") return } redisConfig := redisComponent.GetConfigWithRedisID(redisConfigList, redisID) if redisConfig == nil { clog.Fatalf("redis config not found. [redisID = %s]", redisID) return } _, options := redisComponent.NewClientOption(redisConfig) p.redisClient = redis.NewClient(options) } func (p *actor) buildKey(genPoolID int32, itemID int32) string { return fmt.Sprintf("%s%d:%d", p.redisKeyFormat, genPoolID, itemID) } func (p *actor) saveGenPoolItem(genPoolItem *GenPoolItem) { key := p.buildKey(genPoolItem.GenPoolID, genPoolItem.ItemID) fields := map[string]any{} fields[CountKey] = genPoolItem.Count fields[PeriodEndTimeKey] = genPoolItem.PeriodEndTime err := p.redisClient.HSet(p.ctx, key, fields).Err() if err != nil { clog.Warnf("[saveGenPoolItem] Hset error. [item = %v , err = %v]", genPoolItem, err) } } // 从redis加载产出池数据到缓存 func (p *actor) loadRedisGenPoolItems() { pipeline := p.redisClient.Pipeline() defer pipeline.Close() var cmds []*redis.SliceCmd for _, genPoolRow := range data.GenPool.List() { key := p.buildKey(genPoolRow.ID, genPoolRow.ItemID) cmds = append(cmds, pipeline.HMGet(p.ctx, key, p.redisFields...)) } if _, err := pipeline.Exec(p.ctx); err != nil { clog.Errorf("[LoadRedisGenPoolItems] error: %v", err) return } for i, genPoolRow := range data.GenPool.List() { result, err := cmds[i].Result() if err != nil { clog.Errorf("[LoadRedisGenPoolItems] error: %v", err) continue } genPoolItem := result2GenPoolItem(genPoolRow.ID, genPoolRow.ItemID, result) if genPoolItem.Count > 0 || genPoolItem.PeriodEndTime > 0 { SetGenPoolItemCache(genPoolItem) } } clog.Debugf("load redis genPool items. count = %d", len(cmds)) } func result2GenPoolItem(genPoolID, itemID int32, result []any) *GenPoolItem { item := NewGenPoolItem(genPoolID, itemID) item.Count = cstring.ToInt64D(cstring.ToString(result[0]), 0) item.PeriodEndTime = cstring.ToInt64D(cstring.ToString(result[1]), 0) return item }