game_sync/ranksrv/com/listmgr.go

126 lines
2.9 KiB
Go

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()
}