package com import ( "time" "mongo.games.com/goserver/core/basic" "mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/task" ) // NewListMgr 创建一个列表管理器 // cacheTime 缓存时间,单位秒 // loadFunc 加载函数 func NewListMgr[T any](cacheTime func() int64, loadFunc func(platform string, index int32) ([]T, error)) *ListMgr[T] { return &ListMgr[T]{ platform: make(map[string]map[int32]*DataItem[T]), LoadFunc: loadFunc, CacheTime: cacheTime, } } type funcCall[T any] func([]T, error) type DataItem[T any] struct { Ts int64 // 更新时间 List []T cb []funcCall[T] } type ListMgr[T any] struct { platform map[string]map[int32]*DataItem[T] // 数据库查询方法 // 参数 平台id,类型 LoadFunc func(string, int32) ([]T, error) CacheTime func() int64 } // Get 从缓存中获取数据 func (r *ListMgr[T]) Get(platform string, index int32, f func([]T, error)) { tp := r.platform[platform] if tp == nil { r.platform[platform] = map[int32]*DataItem[T]{} } item := r.platform[platform][index] if item != nil { f(item.List, nil) return } } // Take 从缓存中获取数据,如果缓存中没有数据或缓存过期,则从数据库中获取数据 func (r *ListMgr[T]) Take(platform string, index int32, f func([]T, error)) { tp := r.platform[platform] if tp == nil { r.platform[platform] = map[int32]*DataItem[T]{} } item := r.platform[platform][index] if item != nil && time.Now().Unix()-item.Ts < r.CacheTime() { f(item.List, nil) return } if item == nil { item = &DataItem[T]{ cb: []funcCall[T]{f}, } r.platform[platform][index] = item } else { if len(item.cb) > 0 { item.cb = append(item.cb, f) return } else { item.cb = []funcCall[T]{f} } } var list []T var err error task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { list, err = r.LoadFunc(platform, index) return nil }), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) { r.platform[platform][index] = &DataItem[T]{ List: list, Ts: time.Now().Unix(), } for _, v := range item.cb { v(list, err) } })).Start() } // UpdateCache 更新缓存 // 重新获取数据 func (r *ListMgr[T]) UpdateCache(platform string, index int32) { tp := r.platform[platform] if tp == nil { r.platform[platform] = map[int32]*DataItem[T]{} } item := r.platform[platform][index] if item == nil { item = &DataItem[T]{ cb: []funcCall[T]{}, } r.platform[platform][index] = item } var list []T var err error task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { list, err = r.LoadFunc(platform, index) if err != nil { logger.Logger.Errorf("UpdateCache LoadFunc error:%v", err) } return nil }), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) { if err == nil { r.platform[platform][index] = &DataItem[T]{ List: list, Ts: time.Now().Unix(), } } })).Start() }