feat 初始化

This commit is contained in:
2026-10-29 10:12:22 +08:00
parent 332d812347
commit 09c1df8a22
81 changed files with 2211 additions and 7821 deletions

View File

@@ -0,0 +1,24 @@
package grpcclient
import (
"git.hlsq.asia/alex/proto/proto/rs/rspb"
"git.hlsq.asia/alex/service-common/discover"
"git.hlsq.asia/alex/service-common/discover/common"
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
)
func AdminNewClient(sid ...int64) (rspb.AdminClient, error) {
c, err := discover.FindServer(common.KeyDiscoverAdmin, sid...)
if err != nil {
return nil, err
}
return rspb.NewAdminClient(c), nil
}
func AdminNewClientLB() (rspb.AdminClient, error) {
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameAdmin)
if err != nil {
return nil, err
}
return rspb.NewAdminClient(c), nil
}

View File

@@ -0,0 +1,24 @@
package grpcclient
import (
"git.hlsq.asia/alex/proto/proto/rs/rspb"
"git.hlsq.asia/alex/service-common/discover"
"git.hlsq.asia/alex/service-common/discover/common"
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
)
func AnnouncementNewClient(sid ...int64) (rspb.AnnouncementClient, error) {
c, err := discover.FindServer(common.KeyDiscoverAnnouncement, sid...)
if err != nil {
return nil, err
}
return rspb.NewAnnouncementClient(c), nil
}
func AnnouncementNewClientLB() (rspb.AnnouncementClient, error) {
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameAnnouncement)
if err != nil {
return nil, err
}
return rspb.NewAnnouncementClient(c), nil
}

View File

@@ -0,0 +1,24 @@
package grpcclient
import (
"git.hlsq.asia/alex/proto/proto/rs/rspb"
"git.hlsq.asia/alex/service-common/discover"
"git.hlsq.asia/alex/service-common/discover/common"
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
)
func CourtPhysicalNewClient(sid ...int64) (rspb.CourtPhysicalClient, error) {
c, err := discover.FindServer(common.KeyDiscoverCourtPhysical, sid...)
if err != nil {
return nil, err
}
return rspb.NewCourtPhysicalClient(c), nil
}
func CourtPhysicalNewClientLB() (rspb.CourtPhysicalClient, error) {
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameCourtPhysical)
if err != nil {
return nil, err
}
return rspb.NewCourtPhysicalClient(c), nil
}

View File

@@ -0,0 +1,24 @@
package grpcclient
import (
"git.hlsq.asia/alex/proto/proto/rs/rspb"
"git.hlsq.asia/alex/service-common/discover"
"git.hlsq.asia/alex/service-common/discover/common"
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
)
func CourtNewClient(sid ...int64) (rspb.CourtClient, error) {
c, err := discover.FindServer(common.KeyDiscoverCourt, sid...)
if err != nil {
return nil, err
}
return rspb.NewCourtClient(c), nil
}
func CourtNewClientLB() (rspb.CourtClient, error) {
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameCourt)
if err != nil {
return nil, err
}
return rspb.NewCourtClient(c), nil
}

View File

@@ -1,9 +1,9 @@
package grpcclient
import (
"git.hlsq.asia/alex/proto/proto/rs/rspb"
"git.hlsq.asia/alex/service-common/discover"
"git.hlsq.asia/alex/service-common/discover/common"
"git.hlsq.asia/alex/service-common/proto/rs/rspb"
)
func GatewayNewClient(sid ...int64) (rspb.GatewayClient, error) {

View File

@@ -0,0 +1,24 @@
package grpcclient
import (
"git.hlsq.asia/alex/proto/proto/rs/rspb"
"git.hlsq.asia/alex/service-common/discover"
"git.hlsq.asia/alex/service-common/discover/common"
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
)
func PostNewClient(sid ...int64) (rspb.PostClient, error) {
c, err := discover.FindServer(common.KeyDiscoverPost, sid...)
if err != nil {
return nil, err
}
return rspb.NewPostClient(c), nil
}
func PostNewClientLB() (rspb.PostClient, error) {
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNamePost)
if err != nil {
return nil, err
}
return rspb.NewPostClient(c), nil
}

View File

@@ -1,12 +1,14 @@
package grpcclient
import (
"fmt"
"git.hlsq.asia/alex/proto/proto/rs/rspb"
"git.hlsq.asia/alex/service-common/discover"
"git.hlsq.asia/alex/service-common/discover/common"
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
"git.hlsq.asia/alex/service-common/proto/rs/rspb"
)
// SceneNewClient 根据SID查找场景服,一般不用这个函数
func SceneNewClient(sid ...int64) (rspb.SceneClient, error) {
c, err := discover.FindServer(common.KeyDiscoverScene, sid...)
if err != nil {
@@ -15,6 +17,15 @@ func SceneNewClient(sid ...int64) (rspb.SceneClient, error) {
return rspb.NewSceneClient(c), nil
}
// SceneInstanceNewClient 根据副本唯一编号查找场景服
func SceneInstanceNewClient(uniqueNO int64) (rspb.SceneClient, error) {
sid := discover.FindInstanceByUniqueNo(uniqueNO)
if sid == 0 {
return nil, fmt.Errorf("instance not found: %v", uniqueNO)
}
return SceneNewClient(sid)
}
func SceneNewClientLB() (rspb.SceneClient, error) {
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameScene)
if err != nil {

View File

@@ -0,0 +1,24 @@
package grpcclient
import (
"git.hlsq.asia/alex/proto/proto/rs/rspb"
"git.hlsq.asia/alex/service-common/discover"
"git.hlsq.asia/alex/service-common/discover/common"
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
)
func ThirdPartyNewClient(sid ...int64) (rspb.ThirdPartyClient, error) {
c, err := discover.FindServer(common.KeyDiscoverThirdParty, sid...)
if err != nil {
return nil, err
}
return rspb.NewThirdPartyClient(c), nil
}
func ThirdPartyNewClientLB() (rspb.ThirdPartyClient, error) {
c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameThirdParty)
if err != nil {
return nil, err
}
return rspb.NewThirdPartyClient(c), nil
}

View File

@@ -1,10 +1,10 @@
package grpcclient
import (
"git.hlsq.asia/alex/proto/proto/rs/rspb"
"git.hlsq.asia/alex/service-common/discover"
"git.hlsq.asia/alex/service-common/discover/common"
"git.hlsq.asia/alex/service-common/net/grpc/resolver"
"git.hlsq.asia/alex/service-common/proto/rs/rspb"
)
func UserNewClient(sid ...int64) (rspb.UserClient, error) {

View File

@@ -3,7 +3,11 @@ package grpcclient
import (
"context"
"fmt"
"git.hlsq.asia/alex/proto/proto/rs/rspb"
"git.hlsq.asia/alex/service-common/discover"
"git.hlsq.asia/alex/service-common/discover/common"
"git.hlsq.asia/alex/service-common/log"
"git.hlsq.asia/alex/service-common/utils/locator"
"google.golang.org/grpc"
"google.golang.org/protobuf/proto"
"sync"
@@ -13,6 +17,8 @@ type GatewayFun int
const (
FunToClient GatewayFun = iota
FunBroadcastClient
FunBroadcastChannel
)
var gatewayServer sync.Map // map[string]*gatewayStream
@@ -37,7 +43,11 @@ func findGatewayBySID(sid int64, fun GatewayFun) (*gatewayStream, error) {
var stream grpc.ClientStream
switch fun {
case FunToClient:
stream, err = client.ToClient(context.Background())
stream, err = client.InnerToClient(context.Background())
case FunBroadcastClient:
stream, err = client.InnerBroadcastClient(context.Background())
case FunBroadcastChannel:
stream, err = client.InnerBroadcastChannel(context.Background())
}
if err != nil {
log.Errorf("findGatewayBySID %v err: %v, sid: %v", fun, err, sid)
@@ -53,7 +63,7 @@ func findGatewayBySID(sid int64, fun GatewayFun) (*gatewayStream, error) {
return ss, nil
}
func SendMessageToGateway(sid int64, fun GatewayFun, msg proto.Message, re ...bool) error {
func sendMessageToGateway(sid int64, fun GatewayFun, msg proto.Message, re ...bool) error {
ss, err := findGatewayBySID(sid, fun)
if err != nil {
return err
@@ -71,13 +81,46 @@ func SendMessageToGateway(sid int64, fun GatewayFun, msg proto.Message, re ...bo
}
// 如果没有标识本次是重试的,就重试一次(默认重试)
if re == nil || !re[0] {
return SendMessageToGateway(sid, fun, msg, true)
return sendMessageToGateway(sid, fun, msg, true)
}
return err
}
return nil
}
// SendMessageToClient 单播消息给客户端
func SendMessageToClient(ctx context.Context, usn int64, msg proto.Message, platform ...rspb.PlatformType) error {
if platform == nil || len(platform) == 0 {
return nil
}
for _, pf := range platform {
if gatewaySID := locator.NewLocator(ctx, usn, int32(pf)).LocateGateway(); gatewaySID > 0 {
return sendMessageToGateway(gatewaySID, FunToClient, msg)
}
}
return nil
}
// BroadcastMessageToClient 广播消息给客户端
func BroadcastMessageToClient(msg *rspb.InnerBroadcastClientReq) error {
return broadcastMessageToGateway(FunBroadcastClient, msg)
}
// BroadcastMessageToChannel 广播消息到频道(加入频道的能收到,不区分平台)
func BroadcastMessageToChannel(msg *rspb.InnerBroadcastChannelReq) error {
return broadcastMessageToGateway(FunBroadcastChannel, msg)
}
func broadcastMessageToGateway(fun GatewayFun, msg proto.Message) error {
sidArr := discover.FindServerAllSid(common.KeyDiscoverGateway)
for _, sid := range sidArr {
if err := sendMessageToGateway(sid, fun, msg); err != nil {
return err
}
}
return nil
}
func gatewayKey(sid int64, fun GatewayFun) string {
return fmt.Sprintf("%v-%v", sid, fun)
}

View File

@@ -1,11 +1,14 @@
package grpcconn
import (
"context"
"git.hlsq.asia/alex/service-common/log"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/keepalive"
"google.golang.org/grpc/metadata"
"strconv"
"time"
)
@@ -22,6 +25,7 @@ func NewGrpcConnection(sid int64, address string) (*GrpcConnection, error) {
address,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithStatsHandler(otelgrpc.NewClientHandler()),
grpc.WithUnaryInterceptor(sidInterceptor(sid)),
grpc.WithKeepaliveParams(
keepalive.ClientParameters{
Time: 30 * time.Second, // 保活探测包发送的时间间隔
@@ -41,3 +45,13 @@ func NewGrpcConnection(sid int64, address string) (*GrpcConnection, error) {
func (g *GrpcConnection) GetConnection() *grpc.ClientConn {
return g.conn
}
func sidInterceptor(sid int64) grpc.UnaryClientInterceptor {
sidStr := strconv.Itoa(int(sid))
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
ctx = metadata.AppendToOutgoingContext(ctx,
"X-Sid", sidStr,
)
return invoker(ctx, method, req, reply, cc, opts...)
}
}

View File

@@ -60,3 +60,11 @@ func (p *GrpcConnectionMgr) LoadAll() map[int64]*grpc.ClientConn {
}
return sidM
}
func (p *GrpcConnectionMgr) LoadAllSid() []int64 {
sidArr := make([]int64, 0)
for sid := range p.poolM {
sidArr = append(sidArr, sid)
}
return sidArr
}

View File

@@ -2,8 +2,11 @@ package service
import (
"context"
"encoding/json"
"fmt"
"git.hlsq.asia/alex/proto/proto/rs/rscommon"
"git.hlsq.asia/alex/service-common/log"
"git.hlsq.asia/alex/service-common/net/http/httpresp"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
otelcodes "go.opentelemetry.io/otel/codes"
@@ -12,6 +15,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"strconv"
"time"
)
@@ -25,6 +29,19 @@ func (s *Base) RecoveryInterceptor(ctx context.Context, req interface{}, info *g
return handler(ctx, req)
}
func (s *Base) CheckSID(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
if md, ok := metadata.FromIncomingContext(ctx); ok {
sidArr := md.Get("X-Sid")
if len(sidArr) > 0 {
if strconv.Itoa(int(s.SID)) != sidArr[0] {
err = status.Error(codes.Internal, "SID mismatch")
return
}
}
}
return handler(ctx, req)
}
func (s *Base) LoggingInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
usn := ""
if md, ok := metadata.FromIncomingContext(ctx); ok {
@@ -37,14 +54,17 @@ func (s *Base) LoggingInterceptor(ctx context.Context, req interface{}, info *gr
_, span := otel.Tracer("grpc.interceptor.logging").Start(ctx, info.FullMethod)
defer span.End()
reqString := fmt.Sprintf("[usn:%v] method: %s, Request: %v", usn, info.FullMethod, req)
reqStr, _ := json.Marshal(req)
reqString := fmt.Sprintf("[usn:%v] ↓↓↓ method: %s, Request: %v", usn, info.FullMethod, string(reqStr))
span.SetAttributes(attribute.String("rpc.req", reqString))
span.SetAttributes(attribute.String("usn", usn))
log.Infof(reqString)
start := time.Now()
resp, err = handler(ctx, req)
respString := fmt.Sprintf("[usn:%v] method: %s, Duration: %v, Response: %v, Error: %v", usn, info.FullMethod, time.Since(start), resp, err)
respStr, _ := json.Marshal(resp)
respString := fmt.Sprintf("[usn:%v] ↑↑↑ method: %s, Duration: %v, Response: %v, Error: %v", usn, info.FullMethod, time.Since(start), string(respStr), err)
span.SetAttributes(attribute.String("rpc.resp", respString))
log.Infof(respString)
@@ -53,8 +73,31 @@ func (s *Base) LoggingInterceptor(ctx context.Context, req interface{}, info *gr
span.AddEvent("Stack Trace", trace.WithAttributes(
attribute.String("stack.trace", fmt.Sprintf("%v", stack.StackTrace())),
))
if original, ok := err.(interface{ Original() error }); ok {
if wrap, ok := original.Original().(interface{ Wrap() error }); ok {
err = wrap.Wrap()
} else {
err = checkGRPCError(original.Original())
}
}
} else if wrap, ok := err.(interface{ Wrap() error }); ok {
err = wrap.Wrap()
} else {
err = checkGRPCError(err)
}
span.SetStatus(otelcodes.Error, err.Error())
}
return
}
func checkGRPCError(err error) error {
if original, ok := err.(interface{ GRPCStatus() *status.Status }); ok {
details := original.GRPCStatus().Details()
if len(details) > 0 {
if ei, ok := details[0].(*rscommon.ErrorInfo); ok {
return httpresp.NewCode(int(ei.Code), ei.Msg).Wrap()
}
}
}
return err
}

View File

@@ -39,7 +39,7 @@ type Base struct {
func (s *Base) Init(ready *sync.WaitGroup) {
s.wg = &sync.WaitGroup{}
s.wg.Add(1)
s.SID = utils.SnowflakeInstance().Generate().Int64()
s.SID = utils.SnowflakeInt64()
go func() {
defer s.wg.Done()
defer s.OnClose()
@@ -55,6 +55,7 @@ func (s *Base) Init(ready *sync.WaitGroup) {
options := []grpc.ServerOption{
grpc.ChainUnaryInterceptor(
s.RecoveryInterceptor,
s.CheckSID,
s.LoggingInterceptor,
),
grpc.StatsHandler(otelgrpc.NewServerHandler()),
@@ -79,6 +80,7 @@ func (s *Base) Init(ready *sync.WaitGroup) {
}
// 准备好了
ready.Done()
log.Infof("%v registered grpc sid: %v", s.Target, s.SID)
if err = s.Serve.Serve(lis); err != nil {
log.Errorf("%v Serve err: %v", s.Target, err)
return
@@ -91,7 +93,6 @@ func (s *Base) SetReady() {
if s.healthcheck != nil {
s.healthcheck.SetServingStatus("", grpc_health_v1.HealthCheckResponse_SERVING)
}
log.Infof("%v server ready, port: %v", s.Target, s.Cfg.Port)
}
func (s *Base) Close() {

View File

@@ -1,22 +1,95 @@
package httpresp
import (
"git.hlsq.asia/alex/service-common/proto/rs/rscommon"
"git.hlsq.asia/alex/proto/proto/rs/rscommon"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var (
OK = NewCode(0, "OK")
Failed = NewCode(1, "Failed")
TokenInvalid = NewCode(2, "Token Invalid")
MethodNotAllowed = NewCode(3, "Method Not Allowed")
NotFound = NewCode(4, "Not Found")
ParamError = NewCode(1001, "参数错误")
NameEmpty = NewCode(1002, "名称不能为空")
NameDuplicate = NewCode(1003, "名称或编号不能重复")
ListEmpty = NewCode(1004, "列表不能为空")
RepeatCommit = NewCode(1005, "请勿重复提交")
OK = NewCode(0, "OK")
Failed = NewCode(1, "Failed")
TokenInvalid = NewCode(2, "Token Invalid")
MethodNotAllowed = NewCode(3, "Method Not Allowed")
NotFound = NewCode(4, "Not Found")
TokenForbidden = NewCode(5, "Token Forbidden")
AdminNotExist = NewCode(6, "Admin Not Exist")
ServerMaintenance = NewCode(7, "Server Maintenance")
RequestTooFast = NewCode(8, "Request too fast") // 请求太频繁了
ParamError = NewCode(1001, "参数错误")
PageQueryError = NewCode(1002, "page query param error")
PhoneCodeError = NewCode(1003, "Phone or code error") // 手机验证码错误
PhoneHasBeenBind = NewCode(1004, "Phone number has been bind") // 手机号已经被绑定
WeChatHasBeenBind = NewCode(1005, "WeChat has been bind") // 微信已经被绑定
BindTicketError = NewCode(1006, "Bind ticket error") // 登录绑定凭证无效
RoundIsEnd = NewCode(2001, "Round is end")
RoundNotEnd = NewCode(2002, "Round not end")
NameEmpty = NewCode(1002, "名称不能为空")
NameDuplicate = NewCode(1003, "名称或编号不能重复")
ListEmpty = NewCode(1004, "列表不能为空")
RepeatCommit = NewCode(1005, "请勿重复提交")
// ----------------user 10000-11000--------------------
UserNotFound = NewCode(10001, "User not found")
CharNickNameTooLong = NewCode(10002, "Character nickname too long")
CharNickNameIllegal = NewCode(10003, "Character nickname illegal")
CharNickNameEmpty = NewCode(10004, "Character nickname empty")
CharModelEmpty = NewCode(10005, "Character model empty")
CharModelNotExist = NewCode(10006, "Character model not exist")
CharAvatarEmpty = NewCode(10007, "Character avatar empty")
CharAvatarNotExist = NewCode(10008, "Character avatar not exist")
CharSexInvalid = NewCode(10009, "Character sex invalid")
RewardAlreadyBindError = NewCode(10010, "Reward already bind") // 奖励已绑定
// ----------------SCENE 10010-10100--------------------
SceneRoomNumberGenError = NewCode(10010, "Room number gen error")
RoomNotExistsError = NewCode(10011, "Room not exists error")
RoomPlayerUpperLimit = NewCode(10012, "Room player upper limit") // 房间人数满了
RoomStatusNotAllowEnter = NewCode(10013, "Room status not allow enter") // 房间状态不允许中途进入
PlayerAlreadyInRoom = NewCode(10014, "Player already in room") //玩家已经在房间中
PlayerHandicapNotMeet = NewCode(10015, "Player handicap not meet") //玩家等级不足
NoAvailableRoom = NewCode(10016, "No available room") // 没有符合的房间
SceneRoomDescriptionWidthError = NewCode(10017, "Room description width more than error")
// ----------------court-physical 11001-12000--------------------
CourtPhysicalNotFind = NewCode(11001, "没有找到线下球场配置")
CourtPhysicalNotFindCompetitionl = NewCode(11002, "没有找到比赛")
CourtPhysicalCompetitionlNotPermission = NewCode(11003, "你不是房主无权编辑")
CourtPhysicalCompetitionlNotHole = NewCode(11004, "球场配置错误,没有洞的数据")
CourtPhysicalCompetitionlPlayerUpperLimit = NewCode(11005, "比赛球员已达上限")
CourtPhysicalCompetitionlPlayerIsRoom = NewCode(11006, "用户已在房间")
CourtPhysicalCompetitionlStart = NewCode(11007, "比赛已开始")
CourtPhysicalCompetitionlPlayerJoinFailed = NewCode(11008, "用户加入比赛失败")
CourtPhysicalCompetitionlNotRemovedHomeowner = NewCode(11009, "不能移除房主")
CourtPhysicalCompetitionlNotFindPlayer = NewCode(11010, "房间没有该用户")
CourtPhysicalCompetitionlNotGamePlayer = NewCode(11011, "该用户不是球员")
CourtPhysicalCompetitionlNotIn = NewCode(11012, "该用户不在本局比赛")
CourtPhysicalCompetitionlStartFail = NewCode(11013, "比赛开始初始化数据失败")
CourtPhysicalCompetitionlEnd = NewCode(11014, "比赛已结束")
CourtPhysicalCompetitionlNotStart = NewCode(11015, "比赛未开始")
CourtPhysicalCompetitionlPKFail = NewCode(11016, "PK玩法配置错误")
CourtPhysicalCompetitionlPKTigerNot3Player = NewCode(11017, "PK玩法配置错误:Tiger玩法参赛选手需≥3")
CourtPhysicalCompetitionlPKTigerNotTiger = NewCode(11018, "PK玩法配置错误:Tiger玩法不能没有老虎")
CourtPhysicalCompetitionlPKTigerNotHole = NewCode(11019, "PK玩法配置错误:Tiger玩法至少要选择一个球洞")
CourtPhysicalCompetitionlPKTigerEnhanceFail = NewCode(11020, "PK玩法配置错误:Tiger玩法比洞才有受让杆")
CourtPhysicalCompetitionlPKTigerTopHoleFail = NewCode(11021, "PK玩法配置错误:Tiger玩法比洞才有顶洞和收顶洞")
CourtPhysicalCompetitionlPKRyderCupNot4Player = NewCode(11022, "PK玩法配置错误:莱德杯玩法需4名参赛选手")
CourtPhysicalCompetitionlPKRyderCupLeastFormat = NewCode(11023, "PK玩法配置错误:莱德杯玩法至少要选择一个赛制")
CourtPhysicalCompetitionlPKRyderCupHoleFail = NewCode(11024, "PK玩法配置错误:莱德杯玩法球洞配置冲突")
CourtPhysicalCompetitionlPKRyderCupTeamFail = NewCode(11025, "PK玩法配置错误:莱德杯玩法两队人数不对")
CourtPhysicalCompetitionlNameIllegal = NewCode(11026, "比赛昵称存在违禁词")
CourtPhysicalCompetitionlLinkError = NewCode(11027, "生成微信链接错误")
// 锦标赛 ----------------court 12001-13000--------------------
CourtTournamentNotInvited = NewCode(12002, "仅限受邀用户参赛") // 未在邀请名单内
CourtTournamentHandicapNotMeet = NewCode(12003, "差点不符合参赛要求") // 无有效差点或超出要求区间
CourtTournamentRoundAlreadyStarted = NewCode(12004, "本轮比赛已开始") // 并发重复开赛(竞态)
CourtTournamentRoundNotInProgress = NewCode(12005, "轮次未开始,不能开赛") // 轮次不是进行中
CourtTournamentJoinEnded = NewCode(12006, "已淘汰,无法继续比赛") // 报名已结束(已淘汰)
CourtTournamentPracticeNotAllowed = NewCode(12007, "该锦标赛未开放练习") // 未配置练习次数
CourtTournamentPracticeEnded = NewCode(12008, "比赛已结束,不允许练习") // 决赛结束/已完成/已取消
CourtTournamentPracticeTimesNotEnough = NewCode(12009, "练习次数已用完") // 已练习次数达上限
CourtTournamentShelfStatusNotAllowed = NewCode(12010, "该锦标赛不允许下架") // 该锦标赛不允许下架
)
type Code struct {

View File

@@ -43,5 +43,9 @@ func JsonNotFound(c *gin.Context) {
}
func JsonUnauthorized(c *gin.Context) {
c.JSON(http.StatusUnauthorized, Error(TokenInvalid))
c.JSON(http.StatusOK, Error(TokenInvalid))
}
func JsonMaintenance(c *gin.Context) {
c.JSON(http.StatusOK, Error(ServerMaintenance))
}

View File

@@ -1,9 +1,5 @@
package socket
import (
"time"
)
type Action int
const (
@@ -31,9 +27,8 @@ type ISocketServer interface {
OnOpen(ISocketConn) ([]byte, Action) // 开启连接
OnHandShake(ISocketConn) Action // 开始握手
OnMessage(ISocketConn, []byte) Action // 收到消息
OnPong(ISocketConn)
OnClose(ISocketConn, error) Action // 关闭连接
OnTick() (time.Duration, Action)
OnClose(ISocketConn, error) Action // 关闭连接
OnTick() Action // 定时调用(由网络层决定)
}
// ISocketConn 由网络层实现
@@ -41,7 +36,7 @@ type ISocketConn interface {
GetParam(key string) interface{}
SetParam(key string, values interface{})
RemoteAddr() string
Ping() error // 需要隔一段时间调用一下,建议20s
Ping() error
Write(data []byte) error
Close() error
IsClose() bool

View File

@@ -3,6 +3,8 @@ package websocket
import (
"bytes"
"context"
"fmt"
"git.hlsq.asia/alex/service-common/log"
"git.hlsq.asia/alex/service-common/net/socket"
"github.com/panjf2000/gnet/v2"
"github.com/panjf2000/gnet/v2/pkg/logging"
@@ -31,7 +33,7 @@ func NewWSServer(i socket.ISocketServer, logger logging.Logger, upgradeTimeout t
}
}
func (s *WSServer) Run(addr string, multicore bool, numEventLoop int, tcpNoDelay gnet.TCPSocketOpt, readBufferCap, writeBufferCap int, lockOSThread bool, reusePort, ticker bool, logger logging.Logger) error {
func (s *WSServer) Run(addr string, multicore bool, numEventLoop int, tcpNoDelay gnet.TCPSocketOpt, readBufferCap, writeBufferCap int, lockOSThread bool, reusePort, ticker bool) error {
return gnet.Run(
s,
addr,
@@ -43,7 +45,7 @@ func (s *WSServer) Run(addr string, multicore bool, numEventLoop int, tcpNoDelay
gnet.WithLockOSThread(lockOSThread),
gnet.WithReusePort(reusePort),
gnet.WithTicker(ticker),
gnet.WithLogger(logger),
gnet.WithLogger(s.logger),
)
}
@@ -65,7 +67,7 @@ func (s *WSServer) OnOpen(c gnet.Conn) ([]byte, gnet.Action) {
isUpgrade: false,
openTime: time.Now().Unix(),
buf: bytes.Buffer{},
logger: s.logger,
logger: log.GetLogger().Named(fmt.Sprintf("CONN %v", c.RemoteAddr().String())),
wsMessageBuf: wsMessageBuf{
curHeader: nil,
cachedBuf: bytes.Buffer{},
@@ -86,7 +88,7 @@ func (s *WSServer) OnClose(c gnet.Conn, err error) (action gnet.Action) {
ws, ok := c.Context().(*WSConn)
if ok {
ws.isClose = true
ws.logger.Warnf("connection close, err: %v", err)
ws.logger.Infof("Connection close, err: %v", err)
return gnet.Action(s.i.OnClose(ws, err))
}
return
@@ -121,14 +123,10 @@ func (s *WSServer) OnTraffic(c gnet.Conn) gnet.Action {
return gnet.Close
} else if msg != nil {
for _, m := range msg {
if socket.OpCode(m.OpCode) == socket.OpPong {
s.i.OnPong(ws)
continue
}
if socket.OpCode(m.OpCode) == socket.OpClose {
return gnet.Close
}
if socket.OpCode(m.OpCode) == socket.OpPing {
if socket.OpCode(m.OpCode) == socket.OpPing || socket.OpCode(m.OpCode) == socket.OpPong {
continue
}
a := s.i.OnMessage(ws, m.Payload)
@@ -176,9 +174,8 @@ func (s *WSServer) OnTick() (delay time.Duration, action gnet.Action) {
v.logger.Errorf("upgrade ws time out close socket error: %v", err)
}
}
d, a := s.i.OnTick()
delay = d
action = gnet.Action(a)
delay = 5 * time.Second
action = gnet.Action(s.i.OnTick())
return
}

View File

@@ -4,12 +4,13 @@ import (
"bufio"
"bytes"
"errors"
"io"
"net/url"
"github.com/gobwas/ws"
"github.com/gobwas/ws/wsutil"
"github.com/panjf2000/gnet/v2"
"github.com/panjf2000/gnet/v2/pkg/logging"
"io"
"net/url"
)
// WSConn 实现ISocketConn接口
@@ -22,7 +23,7 @@ type WSConn struct {
isClose bool
param map[string]interface{}
openTime int64 // 开启连接的时间
remoteAddr string // 远程ID地址
remoteAddr string // 远程IP地址
wsMessageBuf
}
@@ -46,7 +47,7 @@ func (w *WSConn) readBytesBuf(c gnet.Conn) gnet.Action {
read, err := c.Read(buf)
if err != nil {
if w.logger != nil {
w.logger.Errorf("ws read bytes buf error", err)
w.logger.Errorf("ws read bytes buf error: %v", err)
}
return gnet.Close
}
@@ -132,7 +133,7 @@ func (w *WSConn) readWsMessages() (messages []wsutil.Message, err error) {
}
} else { //数据不完整
if w.logger != nil {
w.logger.Debugf("ws read ws message incomplete data", in.Len(), dataLen)
w.logger.Debugf("ws read ws message incomplete data ,%v,%v", in.Len(), dataLen)
}
return
}