123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- package memcache
- import (
- "fmt"
- "leafstalk/covenant/monitor"
- "leafstalk/module"
- "leafstalk/otherutils"
- "reflect"
- "strconv"
- "time"
- cach2 "github.com/patrickmn/go-cache"
- )
- type GenericCache[T interface{}] struct {
- AllPlayers *cach2.Cache
- tokens otherutils.RoutineTokens
- loadFilter otherutils.FilterInt64
- skeleton *module.Skeleton
- name string
- Load func(id int64) (*T, error)
- New func(playerId int64) *T
- PrePocess func(*T)
- }
- func NewCache[T interface{}](skeleton *module.Skeleton) *GenericCache[T] {
- c := new(GenericCache[T])
- c.skeleton = skeleton
- var tmp *T
- val := reflect.TypeOf(tmp)
- if val != nil && val.Kind() == reflect.Ptr {
- c.name = val.Elem().Name()
- }
- return c
- }
- type callBackFun[T interface{}] struct {
- fprocess func(p *T)
- fErrProcess func(playerId int64, errorCode int)
- }
- func (c *GenericCache[T]) Init(load func(id int64) (*T, error),
- newObj func(playerId int64) *T, preProcess func(*T)) {
- c.AllPlayers = cach2.New(30*time.Minute, 10*time.Minute)
- c.tokens.Init(10)
- c.Load = load
- c.New = newObj
- c.PrePocess = preProcess
- }
- func (c *GenericCache[T]) GetCacheData(playerID int64) *T {
- k := strconv.FormatInt(playerID, 10)
- if v, ok := c.AllPlayers.Get(k); ok {
- if v2, ok := v.(*T); ok {
- return v2
- }
- }
- return nil
- }
- func (c *GenericCache[T]) SetCacheData(playerID int64, v *T) {
- k2 := strconv.FormatInt(playerID, 10)
- c.AllPlayers.SetDefault(k2, v)
- }
- func (c *GenericCache[T]) LoadAndProcess(playerId int64, fprocess func(p *T), fErrProcess func(playerId int64, errorCode int)) {
- //找到玩家
- st := time.Now()
- p := c.GetCacheData(playerId)
- if p != nil {
- c.PrePocess(p)
- c.SetCacheData(playerId, p)
- fprocess(p)
- monitor.GoLoadTimeoutWarn(fmt.Sprintf("%s.LoadAndProcess", c.name), playerId, st)
- return
- }
- //正在加载
- if c.loadFilter.IsExist(playerId) {
- t := new(callBackFun[T])
- t.fprocess = fprocess
- t.fErrProcess = fErrProcess
- c.loadFilter.AppendTask(playerId, t)
- return
- }
- c.loadFilter.Add(playerId)
- var err error
- c.skeleton.Go(func() {
- //协程加载
- c.tokens.Get()
- defer c.tokens.Release()
- p, err = c.Load(playerId)
- }, func() {
- defer func() {
- s := c.loadFilter.Remove(playerId)
- for _, v := range s {
- cft := v.(*callBackFun[T])
- if err != nil {
- cft.fErrProcess(playerId, 11)
- } else {
- cft.fprocess(p)
- }
- }
- monitor.GoLoadTimeoutWarn(fmt.Sprintf("%s.LoadAndProcess1", c.name), playerId, st)
- }()
- if err != nil {
- fErrProcess(playerId, 11)
- return
- }
- if IsNil(p) || p == nil {
- p = c.New(playerId)
- }
- c.PrePocess(p)
- c.SetCacheData(playerId, p)
- fprocess(p)
- })
- }
- func IsNil(i interface{}) bool {
- vi := reflect.ValueOf(i)
- if vi.Kind() == reflect.Ptr {
- return vi.IsNil()
- }
- return false
- }
- func (c *GenericCache[T]) LoadMultiAndProcess(playerId1 int64, playerId2 int64, fprocess func(p1 *T, p2 *T), fErrProcess func(errorCode int)) {
- c.LoadAndProcess(playerId1, func(p1 *T) {
- c.LoadAndProcess(playerId2, func(p2 *T) {
- fprocess(p1, p2)
- }, func(playerId int64, errorCode int) {
- fErrProcess(errorCode)
- })
- }, func(playerId int64, errorCode int) {
- fErrProcess(errorCode)
- })
- }
|