添加资源rpc

This commit is contained in:
liuxiaobo 2025-06-14 16:40:15 +08:00
parent 15a4b8256a
commit fc13e7625c
18 changed files with 282 additions and 75 deletions

View File

@ -2,17 +2,17 @@ package config
// Common中只有Special会动态更新Special是各类服务自己需要及时更新的配置信息 // Common中只有Special会动态更新Special是各类服务自己需要及时更新的配置信息
type Common struct { type Common struct {
ServiceType int `json:"service_type"` ServiceType int `json:"service_type"`
Logger Logger `json:"logger"` Logger Logger `json:"logger"`
Etcd Etcd `json:"etcd"` Etcd Etcd `json:"etcd"`
Redis Redis `json:"redis"` Redis Redis `json:"redis"`
Nats Nats `json:"nats"` Nats Nats `json:"nats"`
Mysql Mysql `json:"mysql"` UserDb Mysql `json:"user_db"`
MysqlLog Mysql `json:"mysql_log"` LogDb ClickHouse `json:"log_db"`
GameJson string `json:"game_json"` GameJson string `json:"game_json"`
GitCommit string `json:"git_commit"` // 服务当前的hash值 GitCommit string `json:"git_commit"` // 服务当前的hash值
GitBranch string `json:"git_branch"` // 服务当前的版本分支 GitBranch string `json:"git_branch"` // 服务当前的版本分支
BuildDate string `json:"build_date"` // 服务构建时间用作version BuildDate string `json:"build_date"` // 服务构建时间用作version
} }
type Logger struct { type Logger struct {

View File

@ -13,21 +13,29 @@ import (
const ( const (
//ModeDev = "dev" // 开发服 //ModeDev = "dev" // 开发服
etcdKey = "etcd_config" etcdKey = "etcd_config"
etcdAddress = "114.132.124.145:2379" etcdAddress = "114.132.124.145:2379"
natsKey = "nats_config" natsKey = "nats_config"
natsAddress = "nats://114.132.124.145:4222" natsAddress = "nats://114.132.124.145:4222"
redisKey = "redis_config"
redisAddress = testHelper.Host redisKey = "redis_config"
redisPort = testHelper.RedisPort redisAddress = testHelper.Host
redisPassword = testHelper.RedisPassword redisPort = testHelper.RedisPort
mysqlKey = "mysql_config" redisPassword = testHelper.RedisPassword
mysqlAddress = "114.132.124.145"
mysqlPort = "3306" mysqlKey = "mysql_config"
mysqlUser = "game" mysqlAddress = "114.132.124.145"
mysqlPasswd = "fox379@@zyxi" mysqlPort = "3306"
mysqlDBName = "game" mysqlUser = "game"
mysqlLogDBName = "game_log" mysqlPasswd = "fox379@@zyxi"
mysqlDBName = "game"
clickhouseKey = "clickhouse_config"
clickhouseAddress = "114.132.124.145"
clickhousePort = "3306"
clickhouseUser = "game"
clickhousePasswd = "fox379@@zyxi"
clickhouseDBName = "game_log"
) )
func LoadGameConfig(rd *redis.Client, specialKey string, comm *Common) error { func LoadGameConfig(rd *redis.Client, specialKey string, comm *Common) error {
@ -108,17 +116,29 @@ func LoadCommonConfig(rd *redis.Client, GitCommit, GitBranch, BuildDate string)
} }
if s == "" { if s == "" {
log.DebugF("load config:empty mysql key") log.DebugF("load config:empty mysql key")
comm.Mysql = Mysql{Host: mysqlAddress, Port: mysqlPort, Password: mysqlPasswd, Username: mysqlUser, DbName: mysqlDBName} comm.UserDb = Mysql{Host: mysqlAddress, Port: mysqlPort, Password: mysqlPasswd, Username: mysqlUser, DbName: mysqlDBName}
if bs, err := json.Marshal(&comm.Mysql); err == nil { if bs, err := json.Marshal(&comm.UserDb); err == nil {
err = rd.Set(context.Background(), mysqlKey, string(bs), 0).Err() err = rd.Set(context.Background(), mysqlKey, string(bs), 0).Err()
} }
} else { } else {
err = json.Unmarshal([]byte(s), &comm.Mysql) err = json.Unmarshal([]byte(s), &comm.UserDb)
} }
comm.MysqlLog = comm.Mysql // 初始化clickhouse
comm.MysqlLog.DbName = mysqlLogDBName s, err = rd.Get(context.Background(), clickhouseKey).Result()
if err != nil && !errors.Is(err, redis.Nil) {
log.FatalF("init config:%v", err)
return nil, err
}
if s == "" {
log.DebugF("load config:empty mysql key")
comm.LogDb = ClickHouse{Host: clickhouseAddress, Port: clickhousePort, Password: clickhousePasswd, Username: clickhouseUser, DbName: clickhouseDBName}
if bs, err := json.Marshal(&comm.UserDb); err == nil {
err = rd.Set(context.Background(), clickhouseKey, string(bs), 0).Err()
}
} else {
err = json.Unmarshal([]byte(s), &comm.UserDb)
}
return &comm, nil return &comm, nil
} }

View File

@ -16,11 +16,6 @@ const (
TableExpire = 7 * 24 * time.Hour // 七天后过期 TableExpire = 7 * 24 * time.Hour // 七天后过期
) )
type resultT[T any] struct {
ret T
//err error
}
type iTable interface { type iTable interface {
GetId() int64 GetId() int64
TableName() string TableName() string
@ -39,8 +34,8 @@ func NewTableOp[T iTable](db *gorm.DB, rds *redis.Client) *TableOp[T] {
} }
func (s *TableOp[T]) tableName() string { func (s *TableOp[T]) tableName() string {
var result resultT[T] var result utils.TValue[T]
return result.ret.TableName() return result.V.TableName()
} }
func (s *TableOp[T]) redisKey(id int64) string { func (s *TableOp[T]) redisKey(id int64) string {
@ -79,6 +74,16 @@ func (s *TableOp[T]) writeRedis(id int64, t *T) {
s.updateRedis(id, maps) s.updateRedis(id, maps)
} }
// 查看在redis中是否存在
func (s *TableOp[T]) existRedis(t *T) bool {
if s.rds == nil {
return false
}
// 查看redis中是否存在该键
exist, _ := s.rds.Exists(context.Background(), s.redisKey((*t).GetId())).Result()
return exist == 1
}
func (s *TableOp[T]) updateRedis(id int64, maps map[string]any) { func (s *TableOp[T]) updateRedis(id int64, maps map[string]any) {
if s.rds == nil { if s.rds == nil {
return return
@ -89,6 +94,22 @@ func (s *TableOp[T]) updateRedis(id int64, maps map[string]any) {
_ = s.rds.Expire(context.Background(), s.redisKey(id), TableExpire).Err() _ = s.rds.Expire(context.Background(), s.redisKey(id), TableExpire).Err()
} }
func (s *TableOp[T]) addRedis(id int64, maps map[string]int64) map[string]int64 {
if s.rds == nil {
return nil
}
rets := map[string]int64{}
for k, v := range maps {
if ret, err := s.rds.HIncrBy(context.Background(), s.redisKey(id), k, v).Result(); err != nil {
log.ErrorF("redis-key:%v HIncrBy field err: %v", s.redisKey(id), k, err)
} else {
rets[k] = ret
}
}
_ = s.rds.Expire(context.Background(), s.redisKey(id), TableExpire).Err()
return rets
}
func (s *TableOp[T]) deleteRedis(id int64) { func (s *TableOp[T]) deleteRedis(id int64) {
if s.rds == nil { if s.rds == nil {
return return
@ -110,49 +131,63 @@ func (s *TableOp[T]) Find(id int64) (*T, pb.ErrCode) {
if table := s.findByRedis(id); table != nil { if table := s.findByRedis(id); table != nil {
return table, pb.ErrCode_OK return table, pb.ErrCode_OK
} }
var result resultT[T] var result utils.TValue[T]
err := s.db.Where("id = ?", id).First(&result.ret).Error err := s.db.Where("id = ?", id).First(&result.V).Error
if err != nil { if err != nil {
log.DebugF("find table:%v id:%v err:%v", s.tableName(), id, err) log.DebugF("find table:%v id:%v err:%v", s.tableName(), id, err)
return nil, pb.ErrCode_SystemErr return nil, pb.ErrCode_SystemErr
} }
return &result.ret, pb.ErrCode_OK return &result.V, pb.ErrCode_OK
} }
// 根据条件查询只在mysql中查询无法在redis中查询 // 根据条件查询只在mysql中查询无法在redis中查询
func (s *TableOp[T]) FindCondition(condition map[string]any) (*T, error) { func (s *TableOp[T]) FindCondition(condition map[string]any) (*T, error) {
var result resultT[T] var result utils.TValue[T]
err := s.db.Where(condition).First(&result.ret).Error err := s.db.Where(condition).First(&result.V).Error
if err != nil { if err != nil {
log.ErrorF("find table:%v condition:%v err:%v", s.tableName(), utils.JsonMarshal(condition), err) log.ErrorF("find table:%v condition:%v err:%v", s.tableName(), utils.JsonMarshal(condition), err)
return nil, err return nil, err
} }
// 查看redis中是否存在该键不存在则写入数据 // 查看redis中是否存在该键不存在则写入数据
exist, _ := s.rds.Exists(context.Background(), s.redisKey(result.ret.GetId())).Result() if !s.existRedis(&result.V) {
if exist != 1 { s.writeRedis(result.V.GetId(), &result.V)
s.writeRedis(result.ret.GetId(), &result.ret)
} }
return &result.ret, nil return &result.V, nil
} }
func (s *TableOp[T]) Update(id int64, updates map[string]any) (*T, pb.ErrCode) { func (s *TableOp[T]) Update(id int64, updates map[string]any) (*T, pb.ErrCode) {
var result resultT[T] var result utils.TValue[T]
err := s.db.Model(&result.ret).Where("id = ?", id).Updates(updates).Error err := s.db.Model(&result.V).Where("id = ?", id).Updates(updates).Error
if err != nil { if err != nil {
log.ErrorF("update table:%v id:%v err:%v", s.tableName(), id, err) log.ErrorF("update table:%v id:%v err:%v", s.tableName(), id, err)
return nil, pb.ErrCode_SystemErr return nil, pb.ErrCode_SystemErr
} }
s.updateRedis(id, updates) s.updateRedis(id, updates)
return &result.ret, pb.ErrCode_OK return &result.V, pb.ErrCode_OK
}
func (s *TableOp[T]) Add(id int64, res map[string]int64) (map[string]int64, pb.ErrCode) {
addRes := map[string]any{}
for k, v := range res {
addRes[k] = gorm.Expr(fmt.Sprintf("%v + ?", k), v)
}
var result utils.TValue[T]
err := s.db.Model(&result.V).Where("id = ?", id).Updates(addRes).Error
if err != nil {
log.ErrorF("add table:%v id:%v err:%v", s.tableName(), id, err)
return nil, pb.ErrCode_SystemErr
}
rets := s.addRedis(id, res)
return rets, pb.ErrCode_OK
} }
func (s *TableOp[T]) Delete(id int64) (*T, pb.ErrCode) { func (s *TableOp[T]) Delete(id int64) (*T, pb.ErrCode) {
var result resultT[T] var result utils.TValue[T]
err := s.db.Delete(&result.ret, id).Error err := s.db.Delete(&result.V, id).Error
if err != nil { if err != nil {
log.ErrorF("delete table:%v err:%v", s.tableName(), err) log.ErrorF("delete table:%v err:%v", s.tableName(), err)
return nil, pb.ErrCode_SystemErr return nil, pb.ErrCode_SystemErr
} }
s.deleteRedis(id) s.deleteRedis(id)
return &result.ret, pb.ErrCode_OK return &result.V, pb.ErrCode_OK
} }

View File

@ -14,3 +14,28 @@ func (u UserResources) GetId() int64 {
func (u UserResources) TableName() string { func (u UserResources) TableName() string {
return "user_resources" return "user_resources"
} }
type UserResourcesLog struct {
UID int64 `gorm:"uniqueIndex" json:"id"`
ResName string `gorm:"default:0" json:"res_name"` // 资源名
ResAddValue int64 `gorm:"default:0" json:"res_value"` // 资源增加值
ResAfterValue int64 `gorm:"default:0" json:"res_after_value"` // 资源增加后的值
GameId int `gorm:"default:0" json:"game_id"` // 添加资源的玩法id充值等非玩法操作资源则为0
GameNo string `json:"game_no"` // 游戏局id同上
Reason string `json:"reason"` // 原因
}
func (u UserResourcesLog) GetId() int64 {
return 0
}
func (u UserResourcesLog) TableName() string {
return "user_resources_log"
}
type AddUserRes struct {
GameId int `json:"game_id"` // 添加资源的玩法id充值等非玩法操作资源则为0
GameNo string `json:"game_no"` // 游戏局id同上
Reason string `json:"reason"` // 原因
AddRes map[string]int64 `json:"add_res"` // map[资源名]增加值
}

View File

@ -0,0 +1,32 @@
package rpc
import (
"encoding/json"
"game/common/model/user"
"game/common/proto/pb"
"game/common/userBindService"
"github.com/fox/fox/ipb"
"github.com/fox/fox/log"
"github.com/fox/fox/service"
)
// 添加玩家资源,负数为减少
func RpcAddUserRes(bindService *userBindService.UserBindService, s service.IService, uid int64, addUserRes *user.AddUserRes) (map[string]int64, pb.ErrCode) {
node, err := bindService.HashServiceNode(pb.ServiceTypeId_STI_DB, uid)
if err != nil {
log.ErrorF("db service node error:%v", err)
return nil, pb.ErrCode_SystemErr
}
rpcMsg := ipb.MakeRpcMsg(AddUserResources, uid, addUserRes)
rspMsg, err := s.Call(service.RpcTopicEx(node.Name), timeout, rpcMsg)
if err != nil {
log.ErrorF("call rpc:%v err:%s ", rpcMsg.RpcMsgId, err.Error())
return nil, pb.ErrCode_SystemErr
}
if rspMsg.RpcCode == 0 {
res := map[string]int64{}
_ = json.Unmarshal(rspMsg.Msg, &res)
return res, pb.ErrCode_OK
}
return nil, pb.ErrCode(rspMsg.RpcCode)
}

View File

@ -36,6 +36,9 @@ func RpcGetGameUser(bindService *userBindService.UserBindService, s service.ISer
log.ErrorF("call rpc:%v err:%s ", rpcMsg.RpcMsgId, err.Error()) log.ErrorF("call rpc:%v err:%s ", rpcMsg.RpcMsgId, err.Error())
return nil, pb.ErrCode_SystemErr return nil, pb.ErrCode_SystemErr
} }
_ = json.Unmarshal(rspMsg.Msg, us) if rspMsg.RpcCode == 0 {
return us, pb.ErrCode_OK _ = json.Unmarshal(rspMsg.Msg, us)
return us, pb.ErrCode_OK
}
return nil, pb.ErrCode_OK
} }

View File

@ -10,4 +10,5 @@ const (
GetUserByAccountId = "get.user.account.id.rpc" GetUserByAccountId = "get.user.account.id.rpc"
GetUserResources = "get.user.resources.rpc" GetUserResources = "get.user.resources.rpc"
GetGameUser = "get.game.user.rpc" GetGameUser = "get.game.user.rpc"
AddUserResources = "add.user.resources.rpc"
) )

View File

@ -33,4 +33,17 @@ sudo docker run -d \
-e MYSQL_USER=game \ -e MYSQL_USER=game \
-e MYSQL_PASSWORD=fox379@@zyxi \ -e MYSQL_PASSWORD=fox379@@zyxi \
-p 3306:3306 \ -p 3306:3306 \
mysql:8.0 mysql:8.0
docker run -d \
--name clickhouse-server \
-p 8123:8123 \
-p 9000:9000 \
-p 9009:9009 \
-e CLICKHOUSE_DB=game_log \
-e CLICKHOUSE_USER=game \
-e CLICKHOUSE_PASSWORD=fox379@@zyxi \
clickhouse/clickhouse-server
// 进入clickhouse容器连到数据库 show databases;
docker exec -it clickhouse-server clickhouse-client --user game --password fox379@@zyxi

14
go.mod
View File

@ -18,12 +18,12 @@ require (
github.com/nats-io/nats.go v1.42.0 github.com/nats-io/nats.go v1.42.0
golang.org/x/crypto v0.38.0 golang.org/x/crypto v0.38.0
google.golang.org/protobuf v1.33.0 google.golang.org/protobuf v1.33.0
gorm.io/gorm v1.26.1 gorm.io/gorm v1.30.0
) )
require ( require (
github.com/ClickHouse/ch-go v0.65.1 // indirect github.com/ClickHouse/ch-go v0.66.0 // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.34.0 // indirect github.com/ClickHouse/clickhouse-go/v2 v2.36.0 // indirect
github.com/andybalholm/brotli v1.1.1 // indirect github.com/andybalholm/brotli v1.1.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect
@ -35,6 +35,7 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect github.com/gorilla/websocket v1.5.3 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/compress v1.18.0 // indirect
@ -48,15 +49,16 @@ require (
go.etcd.io/etcd/api/v3 v3.5.19 // indirect go.etcd.io/etcd/api/v3 v3.5.19 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.19 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.19 // indirect
go.etcd.io/etcd/client/v3 v3.5.19 // indirect go.etcd.io/etcd/client/v3 v3.5.19 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect go.opentelemetry.io/otel v1.36.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect go.opentelemetry.io/otel/trace v1.36.0 // indirect
golang.org/x/net v0.40.0 // indirect golang.org/x/net v0.40.0 // indirect
golang.org/x/sys v0.33.0 // indirect golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.25.0 // indirect golang.org/x/text v0.26.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
google.golang.org/grpc v1.62.1 // indirect google.golang.org/grpc v1.62.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/clickhouse v0.7.0 // indirect
gorm.io/driver/mysql v1.5.7 // indirect gorm.io/driver/mysql v1.5.7 // indirect
) )

17
go.sum
View File

@ -2,8 +2,13 @@ github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/ClickHouse/ch-go v0.65.1 h1:SLuxmLl5Mjj44/XbINsK2HFvzqup0s6rwKLFH347ZhU= github.com/ClickHouse/ch-go v0.65.1 h1:SLuxmLl5Mjj44/XbINsK2HFvzqup0s6rwKLFH347ZhU=
github.com/ClickHouse/ch-go v0.65.1/go.mod h1:bsodgURwmrkvkBe5jw1qnGDgyITsYErfONKAHn05nv4= github.com/ClickHouse/ch-go v0.65.1/go.mod h1:bsodgURwmrkvkBe5jw1qnGDgyITsYErfONKAHn05nv4=
github.com/ClickHouse/ch-go v0.66.0 h1:hLslxxAVb2PHpbHr4n0d6aP8CEIpUYGMVT1Yj/Q5Img=
github.com/ClickHouse/ch-go v0.66.0/go.mod h1:noiHWyLMJAZ5wYuq3R/K0TcRhrNA8h7o1AqHX0klEhM=
github.com/ClickHouse/clickhouse-go v1.5.4 h1:cKjXeYLNWVJIx2J1K6H2CqyRmfwVJVY1OV1coaaFcI0=
github.com/ClickHouse/clickhouse-go/v2 v2.34.0 h1:Y4rqkdrRHgExvC4o/NTbLdY5LFQ3LHS77/RNFxFX3Co= github.com/ClickHouse/clickhouse-go/v2 v2.34.0 h1:Y4rqkdrRHgExvC4o/NTbLdY5LFQ3LHS77/RNFxFX3Co=
github.com/ClickHouse/clickhouse-go/v2 v2.34.0/go.mod h1:yioSINoRLVZkLyDzdMXPLRIqhDvel8iLBlwh6Iefso8= github.com/ClickHouse/clickhouse-go/v2 v2.34.0/go.mod h1:yioSINoRLVZkLyDzdMXPLRIqhDvel8iLBlwh6Iefso8=
github.com/ClickHouse/clickhouse-go/v2 v2.36.0 h1:FJ03h8VdmBUhvR9nQEu5jRLdfG0c/HSxUjiNdOxRQww=
github.com/ClickHouse/clickhouse-go/v2 v2.36.0/go.mod h1:aijX64fKD1hAWu/zqWEmiGk7wRE8ZnpN0M3UvjsZG3I=
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
@ -42,6 +47,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
@ -112,8 +119,12 @@ go.etcd.io/etcd/client/v3 v3.5.19/go.mod h1:FNzyinmMIl0oVsty1zA3hFeUrxXI/JpEnz4s
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@ -154,6 +165,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@ -184,8 +197,12 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/clickhouse v0.7.0 h1:BCrqvgONayvZRgtuA6hdya+eAW5P2QVagV3OlEp1vtA=
gorm.io/driver/clickhouse v0.7.0/go.mod h1:TmNo0wcVTsD4BBObiRnCahUgHJHjBIwuRejHwYt3JRs=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.26.1 h1:ghB2gUI9FkS46luZtn6DLZ0f6ooBJ5IbVej2ENFDjRw= gorm.io/gorm v1.26.1 h1:ghB2gUI9FkS46luZtn6DLZ0f6ooBJ5IbVej2ENFDjRw=
gorm.io/gorm v1.26.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= gorm.io/gorm v1.26.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=

View File

@ -8,10 +8,7 @@ import (
) )
var Command *config.Command var Command *config.Command
var Cfg *config.Common[DbConfig] var Cfg *config.Common
type DbConfig struct {
}
func InitLog() { func InitLog() {
log.Open("./log/db.log", log.DebugL) log.Open("./log/db.log", log.DebugL)
@ -29,7 +26,7 @@ func LoadConfig(GitCommit, GitBranch, BuildDate string) {
return return
} }
defer func() { _ = rdb.Close() }() defer func() { _ = rdb.Close() }()
Cfg, err = config.LoadCommonConfig[DbConfig](rdb, GitCommit, GitBranch, BuildDate) Cfg, err = config.LoadCommonConfig(rdb, GitCommit, GitBranch, BuildDate)
if err != nil { if err != nil {
log.Error(err.Error()) log.Error(err.Error())
return return

View File

@ -39,14 +39,14 @@ func InitRedis() {
func InitDb() { func InitDb() {
log.Debug("init db") log.Debug("init db")
var err error var err error
cfg := &config.Cfg.Mysql cfg := &config.Cfg.UserDb
UserDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName) UserDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
if err != nil { if err != nil {
log.Fatal(err.Error()) log.Fatal(err.Error())
return return
} }
cfg = &config.Cfg.MysqlLog cfgClickhouse := &config.Cfg.LogDb
LogDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName) LogDB, err = db.InitMysql(cfgClickhouse.Username, cfgClickhouse.Password, cfgClickhouse.Host, cfgClickhouse.Port, cfgClickhouse.DbName)
if err != nil { if err != nil {
log.Fatal(err.Error()) log.Fatal(err.Error())
return return

View File

@ -9,3 +9,8 @@ import (
func NewUserResourcesOp() *model.TableOp[user.UserResources] { func NewUserResourcesOp() *model.TableOp[user.UserResources] {
return model.NewTableOp[user.UserResources](UserDB, UserRedis) return model.NewTableOp[user.UserResources](UserDB, UserRedis)
} }
// 玩家资源表
func NewUserResourcesLogOp() *model.TableOp[user.UserResourcesLog] {
return model.NewTableOp[user.UserResourcesLog](LogDB, nil)
}

View File

@ -6,6 +6,7 @@ import (
"game/common/proto/pb" "game/common/proto/pb"
"game/server/db/operation" "game/server/db/operation"
"github.com/fox/fox/ipb" "github.com/fox/fox/ipb"
"github.com/fox/fox/ksync"
"github.com/fox/fox/log" "github.com/fox/fox/log"
) )
@ -28,20 +29,24 @@ type result[T any] struct {
} }
// 装饰器 // 装饰器
// 返回值存在iMsg.Msg中
func operationDb[T any](iMsg *ipb.InternalMsg, operation func(table *T) (*T, pb.ErrCode)) { func operationDb[T any](iMsg *ipb.InternalMsg, operation func(table *T) (*T, pb.ErrCode)) {
t := result[T]{} t := result[T]{}
err := json.Unmarshal(iMsg.Msg, &t.ret) err := json.Unmarshal(iMsg.Msg, &t.ret)
if err != nil { if err != nil {
log.ErrorF("error unmarshalling user account %v", err) log.ErrorF("error unmarshalling user account %v", err)
iMsg.RpcCode = int32(pb.ErrCode_SystemErr)
return return
} }
table, code := operation(&t.ret) table, code := operation(&t.ret)
if code != pb.ErrCode_OK { if code != pb.ErrCode_OK {
iMsg.RpcCode = int32(code)
return return
} }
iMsg.Msg, err = json.Marshal(table) iMsg.Msg, err = json.Marshal(table)
if err != nil { if err != nil {
log.ErrorF("error marshalling user account %v", err) log.ErrorF("error marshalling user account %v", err)
iMsg.RpcCode = int32(pb.ErrCode_SystemErr)
return return
} }
//log.DebugF("iMsg.Msg:%v", string(iMsg.Msg)) //log.DebugF("iMsg.Msg:%v", string(iMsg.Msg))
@ -91,6 +96,45 @@ func (s *DbService) onGetUserResources(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
return iMsg return iMsg
} }
// 添加用户资源,负数为减少
func (s *DbService) onAddUserResources(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
addUserRes := &user.AddUserRes{}
err := json.Unmarshal(iMsg.Msg, addUserRes)
if err != nil {
log.ErrorF("err:%v unmarshalling user resources %v", err, string(iMsg.Msg))
iMsg.RpcCode = int32(pb.ErrCode_SystemErr)
return iMsg
}
rets, code := operation.NewUserResourcesOp().Add(iMsg.UserId, addUserRes.AddRes)
if code != pb.ErrCode_OK {
iMsg.RpcCode = int32(code)
return iMsg
}
iMsg.Msg, err = json.Marshal(rets)
if err != nil {
log.ErrorF("error marshalling user account %v", err)
iMsg.RpcCode = int32(pb.ErrCode_SystemErr)
return iMsg
}
logOp := operation.NewUserResourcesLogOp()
ksync.GoSafe(func() {
for resName, resAfterValue := range rets {
resAddValue := addUserRes.AddRes[resName]
logOp.Create(&user.UserResourcesLog{
UID: iMsg.UserId,
ResName: resName,
ResAddValue: resAddValue,
ResAfterValue: resAfterValue,
GameId: addUserRes.GameId,
GameNo: addUserRes.GameNo,
Reason: addUserRes.Reason,
})
}
}, nil)
return iMsg
}
// 获取用户数据 // 获取用户数据
func (s *DbService) onGetGameUser(iMsg *ipb.InternalMsg) *ipb.InternalMsg { func (s *DbService) onGetGameUser(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
operationDb[user.GameUser](iMsg, func(gameUser *user.GameUser) (*user.GameUser, pb.ErrCode) { operationDb[user.GameUser](iMsg, func(gameUser *user.GameUser) (*user.GameUser, pb.ErrCode) {

View File

@ -15,5 +15,6 @@ func (s *DbService) initRpcProcessor() {
rpc.GetUserByAccountId: s.onGetUserByAccountId, rpc.GetUserByAccountId: s.onGetUserByAccountId,
rpc.GetUserResources: s.onGetUserResources, rpc.GetUserResources: s.onGetUserResources,
rpc.GetGameUser: s.onGetGameUser, rpc.GetGameUser: s.onGetGameUser,
rpc.AddUserResources: s.onAddUserResources,
}) })
} }

View File

@ -31,13 +31,13 @@ func InitRedis() {
// func InitDb() { // func InitDb() {
// log.Debug("init db") // log.Debug("init db")
// var err error // var err error
// cfg := &config.Cfg.Mysql // cfg := &config.Cfg.UserDb
// UserDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName) // UserDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
// if err != nil { // if err != nil {
// log.Fatal(err.Error()) // log.Fatal(err.Error())
// return // return
// } // }
// cfg = &config.Cfg.MysqlLog // cfg = &config.Cfg.LogDb
// LogDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName) // LogDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
// if err != nil { // if err != nil {
// log.Fatal(err.Error()) // log.Fatal(err.Error())

View File

@ -48,6 +48,10 @@ func (s *LoginService) checkLoginOrRegister(req *pb.ReqUserLogin) (us *user.User
log.ErrorF(s.Log("call rpc:%v err:%s ", rpcMsg.RpcMsgId, err.Error())) log.ErrorF(s.Log("call rpc:%v err:%s ", rpcMsg.RpcMsgId, err.Error()))
return nil, pb.ErrCode_SystemErr, node return nil, pb.ErrCode_SystemErr, node
} }
if rspMsg.RpcCode != 0 {
log.ErrorF(s.Log("call rpc:%v err:%s ", rpcMsg.RpcMsgId, pb.ErrCode(rspMsg.RpcCode)))
return nil, pb.ErrCode(rspMsg.RpcCode), node
}
_ = json.Unmarshal(rspMsg.Msg, us) _ = json.Unmarshal(rspMsg.Msg, us)
//log.DebugF("收到rpc:%v返回数据:%v", rpcName.GetUserAccount, string(rspMsg.Msg)) //log.DebugF("收到rpc:%v返回数据:%v", rpcName.GetUserAccount, string(rspMsg.Msg))
if us.ID == 0 { if us.ID == 0 {
@ -67,6 +71,10 @@ func (s *LoginService) checkLoginOrRegister(req *pb.ReqUserLogin) (us *user.User
log.ErrorF(s.Log("call rpc:%v err:%s ", rpcMsg.RpcMsgId, err.Error())) log.ErrorF(s.Log("call rpc:%v err:%s ", rpcMsg.RpcMsgId, err.Error()))
return nil, pb.ErrCode_SystemErr, node return nil, pb.ErrCode_SystemErr, node
} }
if rspMsg.RpcCode != 0 {
log.ErrorF(s.Log("call rpc:%v err:%s ", rpcMsg.RpcMsgId, pb.ErrCode(rspMsg.RpcCode)))
return nil, pb.ErrCode(rspMsg.RpcCode), node
}
_ = json.Unmarshal(rspMsg.Msg, us) _ = json.Unmarshal(rspMsg.Msg, us)
if us.ID == 0 { if us.ID == 0 {
log.ErrorF(s.Log("call rpc:%v err", rpcMsg.RpcMsgId)) log.ErrorF(s.Log("call rpc:%v err", rpcMsg.RpcMsgId))
@ -108,6 +116,10 @@ func (s *LoginService) getUser(accountId int64, tName string) (*user.User, pb.Er
log.ErrorF(s.Log("call rpc:%v err:%s", rpcMsg.RpcMsgId, err.Error())) log.ErrorF(s.Log("call rpc:%v err:%s", rpcMsg.RpcMsgId, err.Error()))
return nil, pb.ErrCode_SystemErr return nil, pb.ErrCode_SystemErr
} }
if rsp.RpcCode != 0 {
log.ErrorF(s.Log("call rpc:%v err:%s ", rpcMsg.RpcMsgId, pb.ErrCode(rsp.RpcCode)))
return nil, pb.ErrCode(rsp.RpcCode)
}
_ = json.Unmarshal(rsp.Msg, us) _ = json.Unmarshal(rsp.Msg, us)
if us.ID == 0 { if us.ID == 0 {
log.ErrorF(s.Log("call rpc:%v return:%v", rpcMsg.RpcMsgId, string(rsp.Msg))) log.ErrorF(s.Log("call rpc:%v return:%v", rpcMsg.RpcMsgId, string(rsp.Msg)))

View File

@ -39,13 +39,13 @@ func InitRedis() {
// func InitDb() { // func InitDb() {
// log.Debug("init db") // log.Debug("init db")
// var err error // var err error
// cfg := &config.Cfg.Mysql // cfg := &config.Cfg.UserDb
// UserDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName) // UserDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
// if err != nil { // if err != nil {
// log.Fatal(err.Error()) // log.Fatal(err.Error())
// return // return
// } // }
// cfg = &config.Cfg.MysqlLog // cfg = &config.Cfg.LogDb
// LogDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName) // LogDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
// if err != nil { // if err != nil {
// log.Fatal(err.Error()) // log.Fatal(err.Error())