refactor: storage 要求 Load 等函数返回错误信息
This commit is contained in:
parent
7c5edb8bef
commit
0d1a985e69
|
@ -13,12 +13,12 @@ mindmap
|
|||
root((Minotaur))
|
||||
/component 通用组件接口定义
|
||||
/components 通用组件内置实现
|
||||
/config 针对配置导表的配置加载
|
||||
/configuration 配置管理功能
|
||||
/game 游戏通用功能接口定义
|
||||
/builtin 游戏通用功能内置实现
|
||||
/notify 通知功能接口定义
|
||||
/planner 策划相关工具目录
|
||||
/configexport 配置导表功能实现
|
||||
/pce 配置导表功能实现
|
||||
/report 数据埋点及上报功能
|
||||
/server 网络服务器支持
|
||||
/cross 内置跨服功能实现
|
||||
|
@ -113,7 +113,6 @@ func main() {
|
|||
```
|
||||
其他的一些支持事件的结构体(非所有):
|
||||
- `game.Room` 游戏房间实现
|
||||
- `synchronization.Map` 并发安全的`Map`实现
|
||||
- ...
|
||||
### 可选项
|
||||
大部分的 `New` 函数均可使用可选项进行创建,具体函数前缀通常为 `With`。
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
package storage
|
||||
|
||||
// NewGlobalData 创建全局数据
|
||||
func NewGlobalData[T any](name string, storage GlobalDataStorage[T]) *GlobalData[T] {
|
||||
func NewGlobalData[T any](name string, storage GlobalDataStorage[T]) (*GlobalData[T], error) {
|
||||
data := &GlobalData[T]{
|
||||
storage: storage,
|
||||
name: name,
|
||||
data: storage.Load(name),
|
||||
}
|
||||
globalDataSaveHandles = append(globalDataSaveHandles, data.SaveData)
|
||||
return data
|
||||
var err error
|
||||
data.data, err = storage.Load(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// GlobalData 全局数据
|
||||
|
@ -29,8 +32,13 @@ func (slf *GlobalData[T]) GetData() T {
|
|||
}
|
||||
|
||||
// LoadData 加载数据
|
||||
func (slf *GlobalData[T]) LoadData() {
|
||||
slf.data = slf.storage.Load(slf.GetName())
|
||||
func (slf *GlobalData[T]) LoadData() error {
|
||||
data, err := slf.storage.Load(slf.GetName())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slf.data = data
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveData 保存数据
|
||||
|
|
|
@ -4,7 +4,7 @@ package storage
|
|||
type GlobalDataStorage[T any] interface {
|
||||
// Load 加载全局数据
|
||||
// - 当全局数据不存在时,应当返回新的全局数据实例
|
||||
Load(name string) T
|
||||
Load(name string) (T, error)
|
||||
// Save 保存全局数据
|
||||
Save(name string, data T) error
|
||||
}
|
||||
|
|
|
@ -6,13 +6,17 @@ import (
|
|||
)
|
||||
|
||||
// NewIndexData 创建索引数据
|
||||
func NewIndexData[I generic.Ordered, T IndexDataItem[I]](name string, storage IndexDataStorage[I, T]) *IndexData[I, T] {
|
||||
func NewIndexData[I generic.Ordered, T IndexDataItem[I]](name string, storage IndexDataStorage[I, T]) (*IndexData[I, T], error) {
|
||||
data := &IndexData[I, T]{
|
||||
storage: storage,
|
||||
name: name,
|
||||
data: storage.LoadAll(name),
|
||||
}
|
||||
return data
|
||||
var err error
|
||||
data.data, err = storage.LoadAll(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// IndexData 全局数据
|
||||
|
@ -29,11 +33,7 @@ func (slf *IndexData[I, T]) GetName() string {
|
|||
|
||||
// GetData 获取数据
|
||||
func (slf *IndexData[I, T]) GetData(index I) T {
|
||||
data, exist := slf.data[index]
|
||||
if !exist {
|
||||
slf.LoadData(index)
|
||||
data = slf.data[index]
|
||||
}
|
||||
data, _ := slf.data[index]
|
||||
return data
|
||||
}
|
||||
|
||||
|
@ -43,13 +43,23 @@ func (slf *IndexData[I, T]) GetAllData() map[I]T {
|
|||
}
|
||||
|
||||
// LoadData 加载数据
|
||||
func (slf *IndexData[I, T]) LoadData(index I) {
|
||||
slf.data[index] = slf.storage.Load(slf.GetName(), index)
|
||||
func (slf *IndexData[I, T]) LoadData(index I) error {
|
||||
data, err := slf.storage.Load(slf.GetName(), index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slf.data[index] = data
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadAllData 加载所有数据
|
||||
func (slf *IndexData[I, T]) LoadAllData() {
|
||||
slf.data = slf.storage.LoadAll(slf.GetName())
|
||||
func (slf *IndexData[I, T]) LoadAllData() error {
|
||||
data, err := slf.storage.LoadAll(slf.GetName())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slf.data = data
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveData 保存数据
|
||||
|
|
|
@ -9,9 +9,9 @@ import (
|
|||
type IndexDataStorage[I generic.Ordered, T IndexDataItem[I]] interface {
|
||||
// Load 加载特定索引数据
|
||||
// - 通常情况下当数据不存在时,应当返回空指针
|
||||
Load(name string, index I) T
|
||||
Load(name string, index I) (T, error)
|
||||
// LoadAll 加载所有数据
|
||||
LoadAll(name string) map[I]T
|
||||
LoadAll(name string) (map[I]T, error)
|
||||
// Save 保存特定索引数据
|
||||
Save(name string, index I, data T) error
|
||||
// SaveAll 保存所有数据
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
package storage
|
||||
|
||||
import "time"
|
||||
|
||||
var (
|
||||
// globalDataSaveHandles 全局数据保存句柄
|
||||
globalDataSaveHandles []func() error
|
||||
)
|
||||
|
||||
// SaveAll 保存所有数据
|
||||
// - errorHandle 错误处理中如果返回 false 将重试,否则跳过当前保存下一个
|
||||
func SaveAll(errorHandle func(err error) bool, retryInterval time.Duration) {
|
||||
var err error
|
||||
for _, handle := range globalDataSaveHandles {
|
||||
for {
|
||||
if err = handle(); err != nil {
|
||||
if !errorHandle(err) {
|
||||
time.Sleep(retryInterval)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,14 +43,13 @@ type GlobalDataFileStorage[T any] struct {
|
|||
}
|
||||
|
||||
// Load 从文件中加载数据,如果文件不存在则使用 generate 生成数据
|
||||
func (slf *GlobalDataFileStorage[T]) Load(name string) T {
|
||||
func (slf *GlobalDataFileStorage[T]) Load(name string) (T, error) {
|
||||
bytes, err := file.ReadOnce(filepath.Join(slf.dir, fmt.Sprintf("%s.%s", name, slf.suffix)))
|
||||
if err != nil {
|
||||
return slf.generate(name)
|
||||
return slf.generate(name), nil
|
||||
}
|
||||
var data = slf.generate(name)
|
||||
_ = slf.decoder(bytes, data)
|
||||
return data
|
||||
return data, slf.decoder(bytes, data)
|
||||
}
|
||||
|
||||
// Save 将数据保存到文件中
|
||||
|
|
|
@ -15,28 +15,28 @@ type GlobalData struct {
|
|||
|
||||
func TestGlobalDataFileStorage_Save(t *testing.T) {
|
||||
Convey("TestGlobalDataFileStorage_Save", t, func() {
|
||||
data := storage.NewGlobalData[*GlobalData]("global_data_file_test", storages.NewGlobalDataFileStorage[*GlobalData]("./example-data", func(name string) *GlobalData {
|
||||
data, err := storage.NewGlobalData[*GlobalData]("global_data_file_test", storages.NewGlobalDataFileStorage[*GlobalData]("./example-data", func(name string) *GlobalData {
|
||||
return &GlobalData{
|
||||
CreateAt: time.Now(),
|
||||
}
|
||||
}))
|
||||
So(err, ShouldBeNil)
|
||||
data.Handle(func(name string, data *GlobalData) {
|
||||
data.TotalCount = 10
|
||||
})
|
||||
if err := data.SaveData(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
So(data.SaveData(), ShouldBeNil)
|
||||
So(data.GetData().TotalCount, ShouldEqual, 10)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGlobalDataFileStorage_Load(t *testing.T) {
|
||||
Convey("TestGlobalDataFileStorage_Load", t, func() {
|
||||
data := storage.NewGlobalData[*GlobalData]("global_data_file_test", storages.NewGlobalDataFileStorage[*GlobalData]("./example-data", func(name string) *GlobalData {
|
||||
data, err := storage.NewGlobalData[*GlobalData]("global_data_file_test", storages.NewGlobalDataFileStorage[*GlobalData]("./example-data", func(name string) *GlobalData {
|
||||
return &GlobalData{
|
||||
CreateAt: time.Now(),
|
||||
}
|
||||
}))
|
||||
So(err, ShouldBeNil)
|
||||
So(data.GetData().TotalCount, ShouldEqual, 10)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -44,21 +44,20 @@ type IndexDataFileStorage[I generic.Ordered, T storage.IndexDataItem[I]] struct
|
|||
decoder FileStorageDecoder[T]
|
||||
}
|
||||
|
||||
func (slf *IndexDataFileStorage[I, T]) Load(name string, index I) T {
|
||||
func (slf *IndexDataFileStorage[I, T]) Load(name string, index I) (T, error) {
|
||||
bytes, err := file.ReadOnce(filepath.Join(slf.dir, fmt.Sprintf(indexNameFormat, name, index, slf.suffix)))
|
||||
if err != nil {
|
||||
return slf.generate(name, index)
|
||||
return slf.generate(name, index), nil
|
||||
}
|
||||
var data = slf.generate(name, index)
|
||||
_ = slf.decoder(bytes, data)
|
||||
return data
|
||||
return data, slf.decoder(bytes, data)
|
||||
}
|
||||
|
||||
func (slf *IndexDataFileStorage[I, T]) LoadAll(name string) map[I]T {
|
||||
func (slf *IndexDataFileStorage[I, T]) LoadAll(name string) (map[I]T, error) {
|
||||
var result = make(map[I]T)
|
||||
files, err := os.ReadDir(slf.dir)
|
||||
if err != nil {
|
||||
return result
|
||||
return result, err
|
||||
}
|
||||
for _, entry := range files {
|
||||
if entry.IsDir() || !strings.HasPrefix(entry.Name(), name) || !strings.HasSuffix(entry.Name(), slf.suffix) {
|
||||
|
@ -73,7 +72,7 @@ func (slf *IndexDataFileStorage[I, T]) LoadAll(name string) map[I]T {
|
|||
result[data.GetIndex()] = data
|
||||
}
|
||||
}
|
||||
return result
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (slf *IndexDataFileStorage[I, T]) Save(name string, index I, data T) error {
|
||||
|
|
|
@ -18,11 +18,12 @@ func (slf *IndexData[I]) GetIndex() I {
|
|||
|
||||
func TestIndexDataFileStorage_Save(t *testing.T) {
|
||||
Convey("TestIndexDataFileStorage_Save", t, func() {
|
||||
data := storage.NewIndexData[string, *IndexData[string]]("index_data_file_test", storages.NewIndexDataFileStorage[string, *IndexData[string]]("./example-data", func(name string, index string) *IndexData[string] {
|
||||
data, err := storage.NewIndexData[string, *IndexData[string]]("index_data_file_test", storages.NewIndexDataFileStorage[string, *IndexData[string]]("./example-data", func(name string, index string) *IndexData[string] {
|
||||
return &IndexData[string]{ID: index}
|
||||
}, func(name string) *IndexData[string] {
|
||||
return new(IndexData[string])
|
||||
}))
|
||||
So(err, ShouldBeNil)
|
||||
data.Handle("INDEX_001", func(name string, index string, data *IndexData[string]) {
|
||||
data.Value = 10
|
||||
})
|
||||
|
@ -35,11 +36,12 @@ func TestIndexDataFileStorage_Save(t *testing.T) {
|
|||
|
||||
func TestIndexDataFileStorage_Load(t *testing.T) {
|
||||
Convey("TestIndexDataFileStorage_Load", t, func() {
|
||||
data := storage.NewIndexData[string, *IndexData[string]]("index_data_file_test", storages.NewIndexDataFileStorage[string, *IndexData[string]]("./example-data", func(name string, index string) *IndexData[string] {
|
||||
data, err := storage.NewIndexData[string, *IndexData[string]]("index_data_file_test", storages.NewIndexDataFileStorage[string, *IndexData[string]]("./example-data", func(name string, index string) *IndexData[string] {
|
||||
return &IndexData[string]{ID: index}
|
||||
}, func(name string) *IndexData[string] {
|
||||
return new(IndexData[string])
|
||||
}))
|
||||
So(err, ShouldBeNil)
|
||||
So(data.GetData("INDEX_001").Value, ShouldEqual, 10)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue