game/server/db/model/tableOption.go

149 lines
3.6 KiB
Go
Raw Normal View History

2025-05-31 23:34:58 +08:00
package model
import (
"context"
"encoding/json"
"fmt"
"game/common/proto/pb"
"game/common/serialization"
"github.com/fox/fox/log"
"github.com/go-redis/redis/v8"
"gorm.io/gorm"
"time"
)
const (
tableExpire = 7 * 24 * time.Hour // 七天后过期
)
type resultT[T any] struct {
ret T
//err error
}
type iTable interface {
GetId() uint
}
/*
T:Table如果不想操作redis则将rds设置为nil
*/
type TableOp[T iTable] struct {
db *gorm.DB
rds *redis.Client
}
func newTableOp[T iTable](db *gorm.DB, rds *redis.Client) *TableOp[T] {
return &TableOp[T]{db: db, rds: rds}
}
func (s *TableOp[T]) tableName() string {
var result resultT[T]
return s.db.Model(&result.ret).Statement.Table
}
func (s *TableOp[T]) redisKey(id uint) string {
return fmt.Sprintf("%s:%d", s.tableName(), id)
}
func (s *TableOp[T]) findByRedis(id uint) *T {
if s.rds == nil {
return nil
}
maps, err := s.rds.HGetAll(context.Background(), s.redisKey(id)).Result()
if err != nil {
log.ErrorF("redis-key:%v HGetAll err: %v", s.redisKey(id), err)
return nil
}
if len(maps) == 0 {
return nil
}
jsonByte, _ := json.Marshal(maps)
var result resultT[T]
_ = json.Unmarshal(jsonByte, &result.ret)
return &result.ret
}
func (s *TableOp[T]) writeRedis(id uint, t *T) {
if s.rds == nil {
return
}
maps := serialization.StructToMap(t)
if len(maps) == 0 {
log.ErrorF("table struct is empty:%v", s.tableName())
}
s.updateRedis(id, maps)
}
func (s *TableOp[T]) updateRedis(id uint, maps map[string]any) {
if s.rds == nil {
return
}
if err := s.rds.HMSet(context.Background(), s.redisKey(id), maps).Err(); err != nil {
log.ErrorF("redis-key:%v HMSet err: %v", s.redisKey(id), err)
}
_ = s.rds.Expire(context.Background(), s.redisKey(id), tableExpire).Err()
}
func (s *TableOp[T]) deleteRedis(id uint) {
if s.rds == nil {
return
}
_ = s.rds.Del(context.Background(), s.redisKey(id)).Err()
}
func (s *TableOp[T]) Create(t *T) (*T, pb.ErrCode) {
if err := s.db.Create(t).Error; err != nil {
log.ErrorF("create table:%v err:%v", s.tableName(), err)
return nil, pb.ErrCode_SystemErr
}
return t, pb.ErrCode_OK
}
func (s *TableOp[T]) Find(id uint) (*T, pb.ErrCode) {
// 先从redis中查询redis中没有则从mysql中查询
if table := s.findByRedis(id); table != nil {
return table, pb.ErrCode_OK
}
var result resultT[T]
err := s.db.Where("id = ?", id).First(&result.ret).Error
if err != nil {
log.ErrorF("find table:%v id:%v err:%v", s.tableName(), id, err)
return nil, pb.ErrCode_SystemErr
}
return &result.ret, pb.ErrCode_OK
}
//// 根据条件查询只在mysql中查询无法在redis中查询
//func (s *TableOp[T]) FindCondition(condition map[string]any) (*T, error) {
// var result resultT[T]
// err := s.db.Where(condition).First(&result.ret).Error
// if err != nil {
// log.ErrorF("find table:%v condition:%v err:%v", s.tableName(), utils.JsonMarshal(condition), err)
// return nil, err
// }
// return &result.ret, nil
//}
func (s *TableOp[T]) Update(id uint, updates map[string]any) (*T, pb.ErrCode) {
var result resultT[T]
err := s.db.Model(&result.ret).Where("id = ?", id).Updates(updates).Error
if err != nil {
log.ErrorF("update table:%v id:%v err:%v", s.tableName(), id, err)
return nil, pb.ErrCode_SystemErr
}
s.updateRedis(id, updates)
return &result.ret, pb.ErrCode_OK
}
func (s *TableOp[T]) Delete(id uint) (*T, pb.ErrCode) {
var result resultT[T]
err := s.db.Delete(&result.ret, id).Error
if err != nil {
log.ErrorF("delete table:%v err:%v", s.tableName(), err)
return nil, pb.ErrCode_SystemErr
}
s.deleteRedis(id)
return &result.ret, pb.ErrCode_OK
}