admin_backend/client/grpc-client.go
2026-05-28 14:39:23 +08:00

210 lines
5.4 KiB
Go

package client
import (
"backend/msg"
"backend/util"
"context"
"fmt"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
const backendRPCTimeout = 3 * time.Second
type backendCallMeta struct {
AppID int
ServerID int
Method string
Timeout time.Duration
}
type backendInvoker[T any] func(ctx context.Context, client msg.BackendClient) (T, error)
type backendMiddleware[T any] func(meta backendCallMeta, next backendInvoker[T]) backendInvoker[T]
type backendCodeResponse interface {
GetCode() int32
GetMsg() string
}
func executeBackendCall[T any](appID, serverID int, method string, invoke backendInvoker[T], middlewares ...backendMiddleware[T]) (T, error) {
var zero T
serverConfig, err := util.GetServerConfig(appID, serverID)
if err != nil {
return zero, fmt.Errorf("failed to get server config: %w", err)
}
if serverConfig == nil {
return zero, fmt.Errorf("server config not found for AppId %d and ServerId %d", appID, serverID)
}
addr := fmt.Sprintf("%s:%d", serverConfig.Host, serverConfig.GrpcPort)
// TODO 测试
//addr = ":50051"
conn, err := grpc.NewClient(
addr,
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
return zero, fmt.Errorf("failed to connect: %w", err)
}
defer conn.Close()
meta := backendCallMeta{
AppID: appID,
ServerID: serverID,
Method: method,
Timeout: backendRPCTimeout,
}
wrapped := invoke
for index := len(middlewares) - 1; index >= 0; index-- {
wrapped = middlewares[index](meta, wrapped)
}
ctx, cancel := context.WithTimeout(context.Background(), meta.Timeout)
defer cancel()
return wrapped(ctx, msg.NewBackendClient(conn))
}
func wrapRPCError[T any](meta backendCallMeta, next backendInvoker[T]) backendInvoker[T] {
return func(ctx context.Context, client msg.BackendClient) (T, error) {
var zero T
resp, err := next(ctx, client)
if err != nil {
return zero, fmt.Errorf("%s failed: %w", meta.Method, err)
}
return resp, nil
}
}
func ensureBackendCode[T backendCodeResponse](meta backendCallMeta, next backendInvoker[T]) backendInvoker[T] {
return func(ctx context.Context, client msg.BackendClient) (T, error) {
var zero T
resp, err := next(ctx, client)
if err != nil {
return zero, fmt.Errorf("%s failed: %w", meta.Method, err)
}
if resp.GetCode() != 0 {
return zero, fmt.Errorf("%s failed with code: %d, msg: %s", meta.Method, resp.GetCode(), resp.GetMsg())
}
return resp, nil
}
}
func OrderShipping(AppId, ServerId int, req *msg.ReqOrderShipping) error {
_, err := executeBackendCall(
AppId,
ServerId,
"OrderShipping",
func(ctx context.Context, client msg.BackendClient) (*msg.ResOrderShipping, error) {
return client.OrderShipping(ctx, req)
},
ensureBackendCode[*msg.ResOrderShipping],
)
return err
}
func ReloadActivity(AppId, ServerId int, req *msg.ReqActivityCfgReload) error {
_, err := executeBackendCall(
AppId,
ServerId,
"ReloadActivity",
func(ctx context.Context, client msg.BackendClient) (*msg.ResActivityCfgReload, error) {
return client.ReloadActivity(ctx, req)
},
ensureBackendCode[*msg.ResActivityCfgReload],
)
return err
}
func UserDetail(AppId, ServerId int, req *msg.UserDetailParam) (*msg.ResUserDetailInfo, error) {
resp, err := executeBackendCall(
AppId,
ServerId,
"UserDetail",
func(ctx context.Context, client msg.BackendClient) (*msg.ResUserDetail, error) {
return client.UserDetail(ctx, req)
},
ensureBackendCode[*msg.ResUserDetail],
)
if err != nil {
return nil, err
}
return resp.GetInfo(), nil
}
func GetServerInfo(AppId, ServerId int, req *msg.ReqServerInfo) (*msg.ResServerInfo, error) {
return executeBackendCall(
AppId,
ServerId,
"ServerInfo",
func(ctx context.Context, client msg.BackendClient) (*msg.ResServerInfo, error) {
return client.ServerInfo(ctx, req)
},
wrapRPCError[*msg.ResServerInfo],
)
}
func PlayerGm(AppId, ServerId int, req *msg.ReqAdminGm) (*msg.ResAdminGm, error) {
return executeBackendCall(
AppId,
ServerId,
"PlayerGm",
func(ctx context.Context, client msg.BackendClient) (*msg.ResAdminGm, error) {
return client.PlayerGm(ctx, req)
},
wrapRPCError[*msg.ResAdminGm],
)
}
func ServerReload(AppId, ServerId int, req *msg.ReqReload) (*msg.ResBackend, error) {
return executeBackendCall(
AppId,
ServerId,
"ServerReload",
func(ctx context.Context, client msg.BackendClient) (*msg.ResBackend, error) {
return client.ServerReload(ctx, req)
},
wrapRPCError[*msg.ResBackend],
)
}
func BanPlayer(AppId, ServerId int, req *msg.ReqAdminBan) (*msg.ResBackend, error) {
return executeBackendCall(
AppId,
ServerId,
"BanPlayer",
func(ctx context.Context, client msg.BackendClient) (*msg.ResBackend, error) {
return client.BanPlayer(ctx, req)
},
wrapRPCError[*msg.ResBackend],
)
}
func ReloadMail(AppId, ServerId int, req *msg.ReqReloadServerMail) (*msg.ResBackend, error) {
return executeBackendCall(
AppId,
ServerId,
"ReloadMail",
func(ctx context.Context, client msg.BackendClient) (*msg.ResBackend, error) {
return client.ReloadMail(ctx, req)
},
wrapRPCError[*msg.ResBackend],
)
}
func MiniGame(AppId, ServerId int, req *msg.ReqMiniGame) (*msg.ResMiniGame, error) {
return executeBackendCall(
AppId,
ServerId,
"MiniGameReward",
func(ctx context.Context, client msg.BackendClient) (*msg.ResMiniGame, error) {
return client.MiniGame(ctx, req)
},
wrapRPCError[*msg.ResMiniGame],
)
}