210 lines
5.4 KiB
Go
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],
|
|
)
|
|
}
|