From ff1bd1d0b63a34cc79bdb07ff577f813aec517cb Mon Sep 17 00:00:00 2001 From: "DESKTOP-V763RJ7\\Administrator" <835606593@qq.com> Date: Sat, 20 Dec 2025 15:39:25 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E7=BB=93=E6=9E=84=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../proto/ss/grpc_pb/service_user.pb.go | 224 +++ .../proto/ss/grpc_pb/service_user.pb.gw.go | 154 ++ .../proto/ss/grpc_pb/service_user_grpc.pb.go | 105 ++ .../common/proto/ss/ss_common/ss_common.pb.go | 99 +- .../gen/service_gateway.swagger.json | 52 + .../gen/service_scene.swagger.json | 80 + .../gen/service_user.swagger.json | 105 ++ .../ServerInternal/gen/ss_common.swagger.json | 44 + Public/Proto/ServerInternal/gen_proto.bat | 8 +- .../sources/google/api/annotations.proto | 31 + .../sources/google/api/http.proto | 370 +++++ .../sources/google/protobuf/any.proto | 162 ++ .../sources/google/protobuf/descriptor.proto | 1448 +++++++++++++++++ .../ServerInternal/sources/service_user.proto | 23 + .../ServerInternal/sources/ss_common.proto | 7 +- Public/Tools/mysql_model/gen.ps1 | 16 + Public/Tools/mysql_model/gen_model.bat | 5 - .../mysql_model/user_db}/model/users.gen.go | 16 +- .../mysql_model/{dao => user_db}/query/gen.go | 0 .../{dao => user_db}/query/users.gen.go | 18 +- Public/Tools/tidy.bat | 3 + Server/common/db/mysql/client.go | 40 +- Server/common/discover/common/define.go | 12 +- Server/common/go.mod | 4 +- Server/common/net/grpc/grpc_conn/conn.go | 3 +- Server/common/net/grpc/grpc_conn/stats.go | 45 - Server/common/net/grpc/resolver/conn.go | 30 + .../common/net/grpc/resolver/etcd_resolver.go | 84 + .../common/net/grpc/resolver/resolver_mgr.go | 35 + .../common/net/grpc/service/client_scene.go | 9 + Server/common/net/grpc/service/client_user.go | 24 + Server/common/net/grpc/service/service.go | 3 + Server/common/net/http/http_resp/code.go | 46 + Server/common/net/http/http_resp/response.go | 22 + .../proto/ss/grpc_pb/service_user.pb.go | 224 +++ .../proto/ss/grpc_pb/service_user.pb.gw.go | 154 ++ .../proto/ss/grpc_pb/service_user_grpc.pb.go | 105 ++ .../common/proto/ss/ss_common/ss_common.pb.go | 99 +- Server/gateway/app/app.go | 2 +- Server/gateway/app/grpc.go | 2 +- Server/gateway/app/grpc_gateway.go | 63 + Server/gateway/app/web.go | 50 - Server/gateway/app/websocket.go | 2 +- Server/gateway/config/config.dev.yaml | 8 - Server/gateway/config/config.prod.yaml | 8 - Server/gateway/go.mod | 2 +- .../handler/http_handler/helper/base.go | 18 - .../http_handler/helper/render/code.go | 31 - .../http_handler/helper/render/render.go | 39 - .../gateway/handler/http_handler/unique_id.go | 16 - .../grpc_server/server/server.go | 2 +- .../grpc_server/server/server_init.go | 2 +- .../grpc_server/stream_client/scene.go | 0 .../handler/ws_handler/client.go | 0 .../handler/ws_handler/client_write.go | 0 .../handler/ws_handler/event.go | 0 .../handler/ws_handler/handler.go | 4 +- .../handler/ws_handler/manager.go | 0 .../net/http_gateway/middleward.go | 0 .../internal/net/http_gateway/router.go | 54 + .../net/http_gateway/wrapper/error_handler.go | 53 + .../net/http_gateway/wrapper/marshal.go | 42 + .../{ => internal}/net/ws_gateway/server.go | 16 +- Server/gateway/net/http_gateway/router.go | 37 - Server/robot/app/websocket.go | 2 +- Server/robot/{ => internal}/ws/client.go | 0 Server/robot/{ => internal}/ws/handler.go | 0 Server/robot/{ => internal}/ws/manager.go | 0 Server/robot/{ => internal}/ws/router.go | 0 Server/scene/app/grpc.go | 2 +- .../grpc_server/server/server.go | 14 +- .../grpc_server/server/server_init.go | 0 .../grpc_server/stream_client/gateway.go | 0 .../scene/{ => internal}/instance/instance.go | 4 +- .../scene/{ => internal}/instance/manager.go | 0 Server/scene/{ => internal}/npc/npc.go | 0 Server/scene/{ => internal}/npc/player.go | 0 Server/user/Dockerfile | 11 + Server/user/app/app.go | 58 + Server/user/app/base.go | 33 + Server/user/app/db.go | 23 + Server/user/app/grpc.go | 27 + Server/user/config/config.dev.yaml | 27 + Server/user/config/config.go | 25 + Server/user/config/config.prod.yaml | 27 + Server/user/go.mod | 57 + Server/user/go.sum | 199 +++ .../user/internal}/dao/model/users.gen.go | 17 +- .../point => user/internal/dao}/query/gen.go | 0 .../internal/dao}/query/users.gen.go | 20 +- Server/user/internal/dao/repository/users.go | 40 + .../internal/grpc_server/server/server.go | 21 + .../grpc_server/server/server_init.go | 32 + .../grpc_server/stream_client/gateway.go | 65 + Server/user/main.go | 14 + Server/指导方针.md | 176 ++ 96 files changed, 4904 insertions(+), 350 deletions(-) create mode 100644 Public/Proto/ServerInternal/gen/common/proto/ss/grpc_pb/service_user.pb.go create mode 100644 Public/Proto/ServerInternal/gen/common/proto/ss/grpc_pb/service_user.pb.gw.go create mode 100644 Public/Proto/ServerInternal/gen/common/proto/ss/grpc_pb/service_user_grpc.pb.go create mode 100644 Public/Proto/ServerInternal/gen/service_gateway.swagger.json create mode 100644 Public/Proto/ServerInternal/gen/service_scene.swagger.json create mode 100644 Public/Proto/ServerInternal/gen/service_user.swagger.json create mode 100644 Public/Proto/ServerInternal/gen/ss_common.swagger.json create mode 100644 Public/Proto/ServerInternal/sources/google/api/annotations.proto create mode 100644 Public/Proto/ServerInternal/sources/google/api/http.proto create mode 100644 Public/Proto/ServerInternal/sources/google/protobuf/any.proto create mode 100644 Public/Proto/ServerInternal/sources/google/protobuf/descriptor.proto create mode 100644 Public/Proto/ServerInternal/sources/service_user.proto create mode 100644 Public/Tools/mysql_model/gen.ps1 delete mode 100644 Public/Tools/mysql_model/gen_model.bat rename {Server/common/db/mysql/point => Public/Tools/mysql_model/user_db}/model/users.gen.go (62%) rename Public/Tools/mysql_model/{dao => user_db}/query/gen.go (100%) rename Public/Tools/mysql_model/{dao => user_db}/query/users.gen.go (94%) delete mode 100644 Server/common/net/grpc/grpc_conn/stats.go create mode 100644 Server/common/net/grpc/resolver/conn.go create mode 100644 Server/common/net/grpc/resolver/etcd_resolver.go create mode 100644 Server/common/net/grpc/resolver/resolver_mgr.go create mode 100644 Server/common/net/grpc/service/client_user.go create mode 100644 Server/common/net/http/http_resp/code.go create mode 100644 Server/common/net/http/http_resp/response.go create mode 100644 Server/common/proto/ss/grpc_pb/service_user.pb.go create mode 100644 Server/common/proto/ss/grpc_pb/service_user.pb.gw.go create mode 100644 Server/common/proto/ss/grpc_pb/service_user_grpc.pb.go create mode 100644 Server/gateway/app/grpc_gateway.go delete mode 100644 Server/gateway/app/web.go delete mode 100644 Server/gateway/handler/http_handler/helper/base.go delete mode 100644 Server/gateway/handler/http_handler/helper/render/code.go delete mode 100644 Server/gateway/handler/http_handler/helper/render/render.go delete mode 100644 Server/gateway/handler/http_handler/unique_id.go rename Server/gateway/{ => internal}/grpc_server/server/server.go (97%) rename Server/gateway/{ => internal}/grpc_server/server/server_init.go (93%) rename Server/gateway/{ => internal}/grpc_server/stream_client/scene.go (100%) rename Server/gateway/{ => internal}/handler/ws_handler/client.go (100%) rename Server/gateway/{ => internal}/handler/ws_handler/client_write.go (100%) rename Server/gateway/{ => internal}/handler/ws_handler/event.go (100%) rename Server/gateway/{ => internal}/handler/ws_handler/handler.go (96%) rename Server/gateway/{ => internal}/handler/ws_handler/manager.go (100%) rename Server/gateway/{ => internal}/net/http_gateway/middleward.go (100%) create mode 100644 Server/gateway/internal/net/http_gateway/router.go create mode 100644 Server/gateway/internal/net/http_gateway/wrapper/error_handler.go create mode 100644 Server/gateway/internal/net/http_gateway/wrapper/marshal.go rename Server/gateway/{ => internal}/net/ws_gateway/server.go (73%) delete mode 100644 Server/gateway/net/http_gateway/router.go rename Server/robot/{ => internal}/ws/client.go (100%) rename Server/robot/{ => internal}/ws/handler.go (100%) rename Server/robot/{ => internal}/ws/manager.go (100%) rename Server/robot/{ => internal}/ws/router.go (100%) rename Server/scene/{ => internal}/grpc_server/server/server.go (80%) rename Server/scene/{ => internal}/grpc_server/server/server_init.go (100%) rename Server/scene/{ => internal}/grpc_server/stream_client/gateway.go (100%) rename Server/scene/{ => internal}/instance/instance.go (98%) rename Server/scene/{ => internal}/instance/manager.go (100%) rename Server/scene/{ => internal}/npc/npc.go (100%) rename Server/scene/{ => internal}/npc/player.go (100%) create mode 100644 Server/user/Dockerfile create mode 100644 Server/user/app/app.go create mode 100644 Server/user/app/base.go create mode 100644 Server/user/app/db.go create mode 100644 Server/user/app/grpc.go create mode 100644 Server/user/config/config.dev.yaml create mode 100644 Server/user/config/config.go create mode 100644 Server/user/config/config.prod.yaml create mode 100644 Server/user/go.mod create mode 100644 Server/user/go.sum rename {Public/Tools/mysql_model => Server/user/internal}/dao/model/users.gen.go (67%) rename Server/{common/db/mysql/point => user/internal/dao}/query/gen.go (100%) rename Server/{common/db/mysql/point => user/internal/dao}/query/users.gen.go (94%) create mode 100644 Server/user/internal/dao/repository/users.go create mode 100644 Server/user/internal/grpc_server/server/server.go create mode 100644 Server/user/internal/grpc_server/server/server_init.go create mode 100644 Server/user/internal/grpc_server/stream_client/gateway.go create mode 100644 Server/user/main.go create mode 100644 Server/指导方针.md diff --git a/Public/Proto/ServerInternal/gen/common/proto/ss/grpc_pb/service_user.pb.go b/Public/Proto/ServerInternal/gen/common/proto/ss/grpc_pb/service_user.pb.go new file mode 100644 index 0000000..62e73d7 --- /dev/null +++ b/Public/Proto/ServerInternal/gen/common/proto/ss/grpc_pb/service_user.pb.go @@ -0,0 +1,224 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: service_user.proto + +package grpc_pb + +import ( + _ "common/proto/ss/ss_common" + _ "google.golang.org/genproto/googleapis/api/annotations" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type LoginReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Phone string `protobuf:"bytes,1,opt,name=Phone,json=phone,proto3" json:"Phone,omitempty"` // 手机号 + Code string `protobuf:"bytes,2,opt,name=Code,json=code,proto3" json:"Code,omitempty"` // 验证码 +} + +func (x *LoginReq) Reset() { + *x = LoginReq{} + if protoimpl.UnsafeEnabled { + mi := &file_service_user_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoginReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginReq) ProtoMessage() {} + +func (x *LoginReq) ProtoReflect() protoreflect.Message { + mi := &file_service_user_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoginReq.ProtoReflect.Descriptor instead. +func (*LoginReq) Descriptor() ([]byte, []int) { + return file_service_user_proto_rawDescGZIP(), []int{0} +} + +func (x *LoginReq) GetPhone() string { + if x != nil { + return x.Phone + } + return "" +} + +func (x *LoginReq) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +type LoginResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UID int32 `protobuf:"varint,1,opt,name=UID,json=uid,proto3" json:"UID,omitempty"` // 用户ID +} + +func (x *LoginResp) Reset() { + *x = LoginResp{} + if protoimpl.UnsafeEnabled { + mi := &file_service_user_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoginResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginResp) ProtoMessage() {} + +func (x *LoginResp) ProtoReflect() protoreflect.Message { + mi := &file_service_user_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoginResp.ProtoReflect.Descriptor instead. +func (*LoginResp) Descriptor() ([]byte, []int) { + return file_service_user_proto_rawDescGZIP(), []int{1} +} + +func (x *LoginResp) GetUID() int32 { + if x != nil { + return x.UID + } + return 0 +} + +var File_service_user_proto protoreflect.FileDescriptor + +var file_service_user_proto_rawDesc = []byte{ + 0x0a, 0x12, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0x34, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x12, + 0x14, 0x0a, 0x05, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x1d, 0x0a, 0x09, 0x4c, 0x6f, 0x67, + 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x49, 0x44, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x03, 0x75, 0x69, 0x64, 0x32, 0x3e, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, + 0x12, 0x36, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x09, 0x2e, 0x4c, 0x6f, 0x67, 0x69, + 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x0a, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x75, 0x73, + 0x65, 0x72, 0x2f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x42, 0x19, 0x5a, 0x17, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, + 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_service_user_proto_rawDescOnce sync.Once + file_service_user_proto_rawDescData = file_service_user_proto_rawDesc +) + +func file_service_user_proto_rawDescGZIP() []byte { + file_service_user_proto_rawDescOnce.Do(func() { + file_service_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_user_proto_rawDescData) + }) + return file_service_user_proto_rawDescData +} + +var file_service_user_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_service_user_proto_goTypes = []interface{}{ + (*LoginReq)(nil), // 0: LoginReq + (*LoginResp)(nil), // 1: LoginResp +} +var file_service_user_proto_depIdxs = []int32{ + 0, // 0: User.Login:input_type -> LoginReq + 1, // 1: User.Login:output_type -> LoginResp + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_service_user_proto_init() } +func file_service_user_proto_init() { + if File_service_user_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_service_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_service_user_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_service_user_proto_goTypes, + DependencyIndexes: file_service_user_proto_depIdxs, + MessageInfos: file_service_user_proto_msgTypes, + }.Build() + File_service_user_proto = out.File + file_service_user_proto_rawDesc = nil + file_service_user_proto_goTypes = nil + file_service_user_proto_depIdxs = nil +} diff --git a/Public/Proto/ServerInternal/gen/common/proto/ss/grpc_pb/service_user.pb.gw.go b/Public/Proto/ServerInternal/gen/common/proto/ss/grpc_pb/service_user.pb.gw.go new file mode 100644 index 0000000..7e0c4b7 --- /dev/null +++ b/Public/Proto/ServerInternal/gen/common/proto/ss/grpc_pb/service_user.pb.gw.go @@ -0,0 +1,154 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: service_user.proto + +/* +Package grpc_pb is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package grpc_pb + +import ( + "context" + "errors" + "io" + "net/http" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +// Suppress "imported and not used" errors +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) + +func request_User_Login_0(ctx context.Context, marshaler runtime.Marshaler, client UserClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq LoginReq + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.Login(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_User_Login_0(ctx context.Context, marshaler runtime.Marshaler, server UserServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq LoginReq + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.Login(ctx, &protoReq) + return msg, metadata, err +} + +// RegisterUserHandlerServer registers the http handlers for service User to "mux". +// UnaryRPC :call UserServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterUserHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. +func RegisterUserHandlerServer(ctx context.Context, mux *runtime.ServeMux, server UserServer) error { + mux.Handle(http.MethodPost, pattern_User_Login_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/.User/Login", runtime.WithHTTPPathPattern("/user/login")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_User_Login_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_User_Login_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + + return nil +} + +// RegisterUserHandlerFromEndpoint is same as RegisterUserHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterUserHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.NewClient(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + return RegisterUserHandler(ctx, mux, conn) +} + +// RegisterUserHandler registers the http handlers for service User to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterUserHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterUserHandlerClient(ctx, mux, NewUserClient(conn)) +} + +// RegisterUserHandlerClient registers the http handlers for service User +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "UserClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "UserClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "UserClient" to call the correct interceptors. This client ignores the HTTP middlewares. +func RegisterUserHandlerClient(ctx context.Context, mux *runtime.ServeMux, client UserClient) error { + mux.Handle(http.MethodPost, pattern_User_Login_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/.User/Login", runtime.WithHTTPPathPattern("/user/login")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_User_Login_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_User_Login_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + return nil +} + +var ( + pattern_User_Login_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"user", "login"}, "")) +) + +var ( + forward_User_Login_0 = runtime.ForwardResponseMessage +) diff --git a/Public/Proto/ServerInternal/gen/common/proto/ss/grpc_pb/service_user_grpc.pb.go b/Public/Proto/ServerInternal/gen/common/proto/ss/grpc_pb/service_user_grpc.pb.go new file mode 100644 index 0000000..d2c2e73 --- /dev/null +++ b/Public/Proto/ServerInternal/gen/common/proto/ss/grpc_pb/service_user_grpc.pb.go @@ -0,0 +1,105 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v4.25.1 +// source: service_user.proto + +package grpc_pb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// UserClient is the client API for User service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type UserClient interface { + Login(ctx context.Context, in *LoginReq, opts ...grpc.CallOption) (*LoginResp, error) +} + +type userClient struct { + cc grpc.ClientConnInterface +} + +func NewUserClient(cc grpc.ClientConnInterface) UserClient { + return &userClient{cc} +} + +func (c *userClient) Login(ctx context.Context, in *LoginReq, opts ...grpc.CallOption) (*LoginResp, error) { + out := new(LoginResp) + err := c.cc.Invoke(ctx, "/User/Login", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// UserServer is the server API for User service. +// All implementations must embed UnimplementedUserServer +// for forward compatibility +type UserServer interface { + Login(context.Context, *LoginReq) (*LoginResp, error) + mustEmbedUnimplementedUserServer() +} + +// UnimplementedUserServer must be embedded to have forward compatible implementations. +type UnimplementedUserServer struct { +} + +func (UnimplementedUserServer) Login(context.Context, *LoginReq) (*LoginResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method Login not implemented") +} +func (UnimplementedUserServer) mustEmbedUnimplementedUserServer() {} + +// UnsafeUserServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to UserServer will +// result in compilation errors. +type UnsafeUserServer interface { + mustEmbedUnimplementedUserServer() +} + +func RegisterUserServer(s grpc.ServiceRegistrar, srv UserServer) { + s.RegisterService(&User_ServiceDesc, srv) +} + +func _User_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LoginReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServer).Login(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/User/Login", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServer).Login(ctx, req.(*LoginReq)) + } + return interceptor(ctx, in, info, handler) +} + +// User_ServiceDesc is the grpc.ServiceDesc for User service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var User_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "User", + HandlerType: (*UserServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Login", + Handler: _User_Login_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "service_user.proto", +} diff --git a/Public/Proto/ServerInternal/gen/common/proto/ss/ss_common/ss_common.pb.go b/Public/Proto/ServerInternal/gen/common/proto/ss/ss_common/ss_common.pb.go index d070b7b..39424c0 100644 --- a/Public/Proto/ServerInternal/gen/common/proto/ss/ss_common/ss_common.pb.go +++ b/Public/Proto/ServerInternal/gen/common/proto/ss/ss_common/ss_common.pb.go @@ -10,6 +10,7 @@ import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" + sync "sync" ) const ( @@ -19,16 +20,89 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type ErrorInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Msg string `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"` +} + +func (x *ErrorInfo) Reset() { + *x = ErrorInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_ss_common_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ErrorInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ErrorInfo) ProtoMessage() {} + +func (x *ErrorInfo) ProtoReflect() protoreflect.Message { + mi := &file_ss_common_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ErrorInfo.ProtoReflect.Descriptor instead. +func (*ErrorInfo) Descriptor() ([]byte, []int) { + return file_ss_common_proto_rawDescGZIP(), []int{0} +} + +func (x *ErrorInfo) GetCode() int32 { + if x != nil { + return x.Code + } + return 0 +} + +func (x *ErrorInfo) GetMsg() string { + if x != nil { + return x.Msg + } + return "" +} + var File_ss_common_proto protoreflect.FileDescriptor var file_ss_common_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x42, 0x1b, 0x5a, 0x19, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x73, 0x73, 0x2f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x22, 0x31, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, + 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, + 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6d, 0x73, 0x67, 0x42, 0x1b, 0x5a, 0x19, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x73, 0x2f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } -var file_ss_common_proto_goTypes = []interface{}{} +var ( + file_ss_common_proto_rawDescOnce sync.Once + file_ss_common_proto_rawDescData = file_ss_common_proto_rawDesc +) + +func file_ss_common_proto_rawDescGZIP() []byte { + file_ss_common_proto_rawDescOnce.Do(func() { + file_ss_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_ss_common_proto_rawDescData) + }) + return file_ss_common_proto_rawDescData +} + +var file_ss_common_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_ss_common_proto_goTypes = []interface{}{ + (*ErrorInfo)(nil), // 0: ErrorInfo +} var file_ss_common_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type @@ -42,18 +116,33 @@ func file_ss_common_proto_init() { if File_ss_common_proto != nil { return } + if !protoimpl.UnsafeEnabled { + file_ss_common_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ErrorInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_ss_common_proto_rawDesc, NumEnums: 0, - NumMessages: 0, + NumMessages: 1, NumExtensions: 0, NumServices: 0, }, GoTypes: file_ss_common_proto_goTypes, DependencyIndexes: file_ss_common_proto_depIdxs, + MessageInfos: file_ss_common_proto_msgTypes, }.Build() File_ss_common_proto = out.File file_ss_common_proto_rawDesc = nil diff --git a/Public/Proto/ServerInternal/gen/service_gateway.swagger.json b/Public/Proto/ServerInternal/gen/service_gateway.swagger.json new file mode 100644 index 0000000..7bca35c --- /dev/null +++ b/Public/Proto/ServerInternal/gen/service_gateway.swagger.json @@ -0,0 +1,52 @@ +{ + "swagger": "2.0", + "info": { + "title": "service_gateway.proto", + "version": "version not set" + }, + "tags": [ + { + "name": "Gateway" + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": {}, + "definitions": { + "ToClientResp": { + "type": "object" + }, + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": {} + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + } + } +} diff --git a/Public/Proto/ServerInternal/gen/service_scene.swagger.json b/Public/Proto/ServerInternal/gen/service_scene.swagger.json new file mode 100644 index 0000000..0728fe0 --- /dev/null +++ b/Public/Proto/ServerInternal/gen/service_scene.swagger.json @@ -0,0 +1,80 @@ +{ + "swagger": "2.0", + "info": { + "title": "service_scene.proto", + "version": "version not set" + }, + "tags": [ + { + "name": "Scene" + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": {}, + "definitions": { + "ActionResp": { + "type": "object" + }, + "EnterResp": { + "type": "object", + "properties": { + "SceneSID": { + "type": "string", + "format": "int64", + "title": "场景服务ID" + }, + "UniqueNo": { + "type": "string", + "format": "int64", + "title": "副本唯一编号" + }, + "MessageID": { + "type": "integer", + "format": "int32", + "title": "发送给客户端的消息ID" + }, + "Payload": { + "type": "string", + "format": "byte", + "title": "消息负载" + } + } + }, + "LeaveResp": { + "type": "object" + }, + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": {} + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + } + } +} diff --git a/Public/Proto/ServerInternal/gen/service_user.swagger.json b/Public/Proto/ServerInternal/gen/service_user.swagger.json new file mode 100644 index 0000000..bb1152a --- /dev/null +++ b/Public/Proto/ServerInternal/gen/service_user.swagger.json @@ -0,0 +1,105 @@ +{ + "swagger": "2.0", + "info": { + "title": "service_user.proto", + "version": "version not set" + }, + "tags": [ + { + "name": "User" + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": { + "/user/login": { + "post": { + "operationId": "User_Login", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/LoginResp" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LoginReq" + } + } + ], + "tags": [ + "User" + ] + } + } + }, + "definitions": { + "LoginReq": { + "type": "object", + "properties": { + "phone": { + "type": "string", + "title": "手机号" + }, + "code": { + "type": "string", + "title": "验证码" + } + } + }, + "LoginResp": { + "type": "object", + "properties": { + "uid": { + "type": "integer", + "format": "int32", + "title": "用户ID" + } + } + }, + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": {} + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + } + } +} diff --git a/Public/Proto/ServerInternal/gen/ss_common.swagger.json b/Public/Proto/ServerInternal/gen/ss_common.swagger.json new file mode 100644 index 0000000..dfc1a16 --- /dev/null +++ b/Public/Proto/ServerInternal/gen/ss_common.swagger.json @@ -0,0 +1,44 @@ +{ + "swagger": "2.0", + "info": { + "title": "ss_common.proto", + "version": "version not set" + }, + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": {}, + "definitions": { + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": {} + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + } + } +} diff --git a/Public/Proto/ServerInternal/gen_proto.bat b/Public/Proto/ServerInternal/gen_proto.bat index d975972..bd3113c 100644 --- a/Public/Proto/ServerInternal/gen_proto.bat +++ b/Public/Proto/ServerInternal/gen_proto.bat @@ -4,5 +4,11 @@ if not exist "./gen" ( mkdir "./gen" ) -protoc --proto_path=./sources --go_out=./gen --go-grpc_out=./gen ./sources/*.proto +protoc ^ +--proto_path=./sources ^ +--go_out=./gen ^ +--go-grpc_out=./gen ^ +--grpc-gateway_out=./gen ^ +--openapiv2_out=./gen ^ +./sources/*.proto xcopy "./gen/common" "../../../Server/common" /E /I /Y /Q \ No newline at end of file diff --git a/Public/Proto/ServerInternal/sources/google/api/annotations.proto b/Public/Proto/ServerInternal/sources/google/api/annotations.proto new file mode 100644 index 0000000..417edd8 --- /dev/null +++ b/Public/Proto/ServerInternal/sources/google/api/annotations.proto @@ -0,0 +1,31 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/http.proto"; +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "AnnotationsProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.MethodOptions { + // See `HttpRule`. + HttpRule http = 72295728; +} diff --git a/Public/Proto/ServerInternal/sources/google/api/http.proto b/Public/Proto/ServerInternal/sources/google/api/http.proto new file mode 100644 index 0000000..57621b5 --- /dev/null +++ b/Public/Proto/ServerInternal/sources/google/api/http.proto @@ -0,0 +1,370 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "HttpProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Defines the HTTP configuration for an API service. It contains a list of +// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method +// to one or more HTTP REST API methods. +message Http { + // A list of HTTP configuration rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated HttpRule rules = 1; + + // When set to true, URL path parameters will be fully URI-decoded except in + // cases of single segment matches in reserved expansion, where "%2F" will be + // left encoded. + // + // The default behavior is to not decode RFC 6570 reserved characters in multi + // segment matches. + bool fully_decode_reserved_expansion = 2; +} + +// gRPC Transcoding +// +// gRPC Transcoding is a feature for mapping between a gRPC method and one or +// more HTTP REST endpoints. It allows developers to build a single API service +// that supports both gRPC APIs and REST APIs. Many systems, including [Google +// APIs](https://github.com/googleapis/googleapis), +// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC +// Gateway](https://github.com/grpc-ecosystem/grpc-gateway), +// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature +// and use it for large scale production services. +// +// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies +// how different portions of the gRPC request message are mapped to the URL +// path, URL query parameters, and HTTP request body. It also controls how the +// gRPC response message is mapped to the HTTP response body. `HttpRule` is +// typically specified as an `google.api.http` annotation on the gRPC method. +// +// Each mapping specifies a URL path template and an HTTP method. The path +// template may refer to one or more fields in the gRPC request message, as long +// as each field is a non-repeated field with a primitive (non-message) type. +// The path template controls how fields of the request message are mapped to +// the URL path. +// +// Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/{name=messages/*}" +// }; +// } +// } +// message GetMessageRequest { +// string name = 1; // Mapped to URL path. +// } +// message Message { +// string text = 1; // The resource content. +// } +// +// This enables an HTTP REST to gRPC mapping as below: +// +// - HTTP: `GET /v1/messages/123456` +// - gRPC: `GetMessage(name: "messages/123456")` +// +// Any fields in the request message which are not bound by the path template +// automatically become HTTP query parameters if there is no HTTP request body. +// For example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get:"/v1/messages/{message_id}" +// }; +// } +// } +// message GetMessageRequest { +// message SubMessage { +// string subfield = 1; +// } +// string message_id = 1; // Mapped to URL path. +// int64 revision = 2; // Mapped to URL query parameter `revision`. +// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. +// } +// +// This enables a HTTP JSON to RPC mapping as below: +// +// - HTTP: `GET /v1/messages/123456?revision=2&sub.subfield=foo` +// - gRPC: `GetMessage(message_id: "123456" revision: 2 sub: +// SubMessage(subfield: "foo"))` +// +// Note that fields which are mapped to URL query parameters must have a +// primitive type or a repeated primitive type or a non-repeated message type. +// In the case of a repeated type, the parameter can be repeated in the URL +// as `...?param=A¶m=B`. In the case of a message type, each field of the +// message is mapped to a separate parameter, such as +// `...?foo.a=A&foo.b=B&foo.c=C`. +// +// For HTTP methods that allow a request body, the `body` field +// specifies the mapping. Consider a REST update method on the +// message resource collection: +// +// service Messaging { +// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "message" +// }; +// } +// } +// message UpdateMessageRequest { +// string message_id = 1; // mapped to the URL +// Message message = 2; // mapped to the body +// } +// +// The following HTTP JSON to RPC mapping is enabled, where the +// representation of the JSON in the request body is determined by +// protos JSON encoding: +// +// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` +// - gRPC: `UpdateMessage(message_id: "123456" message { text: "Hi!" })` +// +// The special name `*` can be used in the body mapping to define that +// every field not bound by the path template should be mapped to the +// request body. This enables the following alternative definition of +// the update method: +// +// service Messaging { +// rpc UpdateMessage(Message) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "*" +// }; +// } +// } +// message Message { +// string message_id = 1; +// string text = 2; +// } +// +// +// The following HTTP JSON to RPC mapping is enabled: +// +// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` +// - gRPC: `UpdateMessage(message_id: "123456" text: "Hi!")` +// +// Note that when using `*` in the body mapping, it is not possible to +// have HTTP parameters, as all fields not bound by the path end in +// the body. This makes this option more rarely used in practice when +// defining REST APIs. The common usage of `*` is in custom methods +// which don't use the URL at all for transferring data. +// +// It is possible to define multiple HTTP methods for one RPC by using +// the `additional_bindings` option. Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/messages/{message_id}" +// additional_bindings { +// get: "/v1/users/{user_id}/messages/{message_id}" +// } +// }; +// } +// } +// message GetMessageRequest { +// string message_id = 1; +// string user_id = 2; +// } +// +// This enables the following two alternative HTTP JSON to RPC mappings: +// +// - HTTP: `GET /v1/messages/123456` +// - gRPC: `GetMessage(message_id: "123456")` +// +// - HTTP: `GET /v1/users/me/messages/123456` +// - gRPC: `GetMessage(user_id: "me" message_id: "123456")` +// +// Rules for HTTP mapping +// +// 1. Leaf request fields (recursive expansion nested messages in the request +// message) are classified into three categories: +// - Fields referred by the path template. They are passed via the URL path. +// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They +// are passed via the HTTP +// request body. +// - All other fields are passed via the URL query parameters, and the +// parameter name is the field path in the request message. A repeated +// field can be represented as multiple query parameters under the same +// name. +// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL +// query parameter, all fields +// are passed via URL path and HTTP request body. +// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP +// request body, all +// fields are passed via URL path and URL query parameters. +// +// Path template syntax +// +// Template = "/" Segments [ Verb ] ; +// Segments = Segment { "/" Segment } ; +// Segment = "*" | "**" | LITERAL | Variable ; +// Variable = "{" FieldPath [ "=" Segments ] "}" ; +// FieldPath = IDENT { "." IDENT } ; +// Verb = ":" LITERAL ; +// +// The syntax `*` matches a single URL path segment. The syntax `**` matches +// zero or more URL path segments, which must be the last part of the URL path +// except the `Verb`. +// +// The syntax `Variable` matches part of the URL path as specified by its +// template. A variable template must not contain other variables. If a variable +// matches a single path segment, its template may be omitted, e.g. `{var}` +// is equivalent to `{var=*}`. +// +// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` +// contains any reserved character, such characters should be percent-encoded +// before the matching. +// +// If a variable contains exactly one path segment, such as `"{var}"` or +// `"{var=*}"`, when such a variable is expanded into a URL path on the client +// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The +// server side does the reverse decoding. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{var}`. +// +// If a variable contains multiple path segments, such as `"{var=foo/*}"` +// or `"{var=**}"`, when such a variable is expanded into a URL path on the +// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. +// The server side does the reverse decoding, except "%2F" and "%2f" are left +// unchanged. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{+var}`. +// +// Using gRPC API Service Configuration +// +// gRPC API Service Configuration (service config) is a configuration language +// for configuring a gRPC service to become a user-facing product. The +// service config is simply the YAML representation of the `google.api.Service` +// proto message. +// +// As an alternative to annotating your proto file, you can configure gRPC +// transcoding in your service config YAML files. You do this by specifying a +// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same +// effect as the proto annotation. This can be particularly useful if you +// have a proto that is reused in multiple services. Note that any transcoding +// specified in the service config will override any matching transcoding +// configuration in the proto. +// +// The following example selects a gRPC method and applies an `HttpRule` to it: +// +// http: +// rules: +// - selector: example.v1.Messaging.GetMessage +// get: /v1/messages/{message_id}/{sub.subfield} +// +// Special notes +// +// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the +// proto to JSON conversion must follow the [proto3 +// specification](https://developers.google.com/protocol-buffers/docs/proto3#json). +// +// While the single segment variable follows the semantics of +// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String +// Expansion, the multi segment variable **does not** follow RFC 6570 Section +// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion +// does not expand special characters like `?` and `#`, which would lead +// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding +// for multi segment variables. +// +// The path variables **must not** refer to any repeated or mapped field, +// because client libraries are not capable of handling such variable expansion. +// +// The path variables **must not** capture the leading "/" character. The reason +// is that the most common use case "{var}" does not capture the leading "/" +// character. For consistency, all path variables must share the same behavior. +// +// Repeated message fields must not be mapped to URL query parameters, because +// no client library can support such complicated mapping. +// +// If an API needs to use a JSON array for request or response body, it can map +// the request or response body to a repeated field. However, some gRPC +// Transcoding implementations may not support this feature. +message HttpRule { + // Selects a method to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + string selector = 1; + + // Determines the URL pattern is matched by this rules. This pattern can be + // used with any of the {get|put|post|delete|patch} methods. A custom method + // can be defined using the 'custom' field. + oneof pattern { + // Maps to HTTP GET. Used for listing and getting information about + // resources. + string get = 2; + + // Maps to HTTP PUT. Used for replacing a resource. + string put = 3; + + // Maps to HTTP POST. Used for creating a resource or performing an action. + string post = 4; + + // Maps to HTTP DELETE. Used for deleting a resource. + string delete = 5; + + // Maps to HTTP PATCH. Used for updating a resource. + string patch = 6; + + // The custom pattern is used for specifying an HTTP method that is not + // included in the `pattern` field, such as HEAD, or "*" to leave the + // HTTP method unspecified for this rule. The wild-card rule is useful + // for services that provide content to Web (HTML) clients. + CustomHttpPattern custom = 8; + } + + // The name of the request field whose value is mapped to the HTTP request + // body, or `*` for mapping all request fields not captured by the path + // pattern to the HTTP body, or omitted for not having any HTTP request body. + // + // NOTE: the referred field must be present at the top-level of the request + // message type. + string body = 7; + + // Optional. The name of the response field whose value is mapped to the HTTP + // response body. When omitted, the entire response message will be used + // as the HTTP response body. + // + // NOTE: The referred field must be present at the top-level of the response + // message type. + string response_body = 12; + + // Additional HTTP bindings for the selector. Nested bindings must + // not contain an `additional_bindings` field themselves (that is, + // the nesting may only be one level deep). + repeated HttpRule additional_bindings = 11; +} + +// A custom pattern is used for defining custom HTTP verb. +message CustomHttpPattern { + // The name of this custom HTTP verb. + string kind = 1; + + // The path matched by this custom verb. + string path = 2; +} diff --git a/Public/Proto/ServerInternal/sources/google/protobuf/any.proto b/Public/Proto/ServerInternal/sources/google/protobuf/any.proto new file mode 100644 index 0000000..eff44e5 --- /dev/null +++ b/Public/Proto/ServerInternal/sources/google/protobuf/any.proto @@ -0,0 +1,162 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option go_package = "google.golang.org/protobuf/types/known/anypb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "AnyProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; + +// `Any` contains an arbitrary serialized protocol buffer message along with a +// URL that describes the type of the serialized message. +// +// Protobuf library provides support to pack/unpack Any values in the form +// of utility functions or additional generated methods of the Any type. +// +// Example 1: Pack and unpack a message in C++. +// +// Foo foo = ...; +// Any any; +// any.PackFrom(foo); +// ... +// if (any.UnpackTo(&foo)) { +// ... +// } +// +// Example 2: Pack and unpack a message in Java. +// +// Foo foo = ...; +// Any any = Any.pack(foo); +// ... +// if (any.is(Foo.class)) { +// foo = any.unpack(Foo.class); +// } +// // or ... +// if (any.isSameTypeAs(Foo.getDefaultInstance())) { +// foo = any.unpack(Foo.getDefaultInstance()); +// } +// +// Example 3: Pack and unpack a message in Python. +// +// foo = Foo(...) +// any = Any() +// any.Pack(foo) +// ... +// if any.Is(Foo.DESCRIPTOR): +// any.Unpack(foo) +// ... +// +// Example 4: Pack and unpack a message in Go +// +// foo := &pb.Foo{...} +// any, err := anypb.New(foo) +// if err != nil { +// ... +// } +// ... +// foo := &pb.Foo{} +// if err := any.UnmarshalTo(foo); err != nil { +// ... +// } +// +// The pack methods provided by protobuf library will by default use +// 'type.googleapis.com/full.type.name' as the type URL and the unpack +// methods only use the fully qualified type name after the last '/' +// in the type URL, for example "foo.bar.com/x/y.z" will yield type +// name "y.z". +// +// JSON +// ==== +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": , +// "lastName": +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the `@type` +// field. Example (for message [google.protobuf.Duration][]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +// +message Any { + // A URL/resource name that uniquely identifies the type of the serialized + // protocol buffer message. This string must contain at least + // one "/" character. The last segment of the URL's path must represent + // the fully qualified name of the type (as in + // `path/google.protobuf.Duration`). The name should be in a canonical form + // (e.g., leading "." is not accepted). + // + // In practice, teams usually precompile into the binary all types that they + // expect it to use in the context of Any. However, for URLs which use the + // scheme `http`, `https`, or no scheme, one can optionally set up a type + // server that maps type URLs to message definitions as follows: + // + // * If no scheme is provided, `https` is assumed. + // * An HTTP GET on the URL must yield a [google.protobuf.Type][] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Note: this functionality is not currently available in the official + // protobuf release, and it is not used for type URLs beginning with + // type.googleapis.com. As of May 2023, there are no widely used type server + // implementations and no plans to implement one. + // + // Schemes other than `http`, `https` (or the empty scheme) might be + // used with implementation specific semantics. + // + string type_url = 1; + + // Must be a valid serialized protocol buffer of the above specified type. + bytes value = 2; +} diff --git a/Public/Proto/ServerInternal/sources/google/protobuf/descriptor.proto b/Public/Proto/ServerInternal/sources/google/protobuf/descriptor.proto new file mode 100644 index 0000000..e5683a2 --- /dev/null +++ b/Public/Proto/ServerInternal/sources/google/protobuf/descriptor.proto @@ -0,0 +1,1448 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + +syntax = "proto2"; + +package google.protobuf; + +option go_package = "google.golang.org/protobuf/types/descriptorpb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; +option csharp_namespace = "Google.Protobuf.Reflection"; +option objc_class_prefix = "GPB"; +option cc_enable_arenas = true; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; + + // Extensions for tooling. + extensions 536000000 [declaration = { + number: 536000000 + type: ".buf.descriptor.v1.FileDescriptorSetExtension" + full_name: ".buf.descriptor.v1.buf_file_descriptor_set_extension" + }]; +} + +// The full set of known editions. +enum Edition { + // A placeholder for an unknown edition value. + EDITION_UNKNOWN = 0; + + // A placeholder edition for specifying default behaviors *before* a feature + // was first introduced. This is effectively an "infinite past". + EDITION_LEGACY = 900; + + // Legacy syntax "editions". These pre-date editions, but behave much like + // distinct editions. These can't be used to specify the edition of proto + // files, but feature definitions must supply proto2/proto3 defaults for + // backwards compatibility. + EDITION_PROTO2 = 998; + EDITION_PROTO3 = 999; + + // Editions that have been released. The specific values are arbitrary and + // should not be depended on, but they will always be time-ordered for easy + // comparison. + EDITION_2023 = 1000; + EDITION_2024 = 1001; + + // A placeholder edition for developing and testing unscheduled features. + EDITION_UNSTABLE = 9999; + + // Placeholder editions for testing feature resolution. These should not be + // used or relied on outside of tests. + EDITION_1_TEST_ONLY = 1; + EDITION_2_TEST_ONLY = 2; + EDITION_99997_TEST_ONLY = 99997; + EDITION_99998_TEST_ONLY = 99998; + EDITION_99999_TEST_ONLY = 99999; + + // Placeholder for specifying unbounded edition support. This should only + // ever be used by plugins that can expect to never require any changes to + // support a new edition. + EDITION_MAX = 0x7FFFFFFF; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + // Indexes of the public imported files in the dependency list above. + repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + repeated int32 weak_dependency = 11; + + // Names of files imported by this file purely for the purpose of providing + // option extensions. These are excluded from the dependency list above. + repeated string option_dependency = 15; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field without harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; + + // The syntax of the proto file. + // The supported values are "proto2", "proto3", and "editions". + // + // If `edition` is present, this value must be "editions". + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional string syntax = 12; + + // The edition of the proto file. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional Edition edition = 14; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + + optional ExtensionRangeOptions options = 3; + } + repeated ExtensionRange extension_range = 5; + + repeated OneofDescriptorProto oneof_decl = 8; + + optional MessageOptions options = 7; + + // Range of reserved tag numbers. Reserved tag numbers may not be used by + // fields or extension ranges in the same message. Reserved ranges may + // not overlap. + message ReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + } + repeated ReservedRange reserved_range = 9; + // Reserved field names, which may not be used by fields in the same message. + // A given name may only be reserved once. + repeated string reserved_name = 10; + + // Support for `export` and `local` keywords on enums. + optional SymbolVisibility visibility = 11; +} + +message ExtensionRangeOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + message Declaration { + // The extension number declared within the extension range. + optional int32 number = 1; + + // The fully-qualified name of the extension field. There must be a leading + // dot in front of the full name. + optional string full_name = 2; + + // The fully-qualified type name of the extension field. Unlike + // Metadata.type, Declaration.type must have a leading dot for messages + // and enums. + optional string type = 3; + + // If true, indicates that the number is reserved in the extension range, + // and any extension field with the number will fail to compile. Set this + // when a declared extension field is deleted. + optional bool reserved = 5; + + // If true, indicates that the extension must be defined as repeated. + // Otherwise the extension must be defined as optional. + optional bool repeated = 6; + + reserved 4; // removed is_repeated + } + + // For external users: DO NOT USE. We are in the process of open sourcing + // extension declaration and executing internal cleanups before it can be + // used externally. + repeated Declaration declaration = 2 [retention = RETENTION_SOURCE]; + + // Any features defined in the specific edition. + optional FeatureSet features = 50; + + // The verification state of the extension range. + enum VerificationState { + // All the extensions of the range must be declared. + DECLARATION = 0; + UNVERIFIED = 1; + } + + // The verification state of the range. + // TODO: flip the default to DECLARATION once all empty ranges + // are marked as UNVERIFIED. + optional VerificationState verification = 3 + [default = UNVERIFIED, retention = RETENTION_SOURCE]; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + TYPE_INT64 = 3; + TYPE_UINT64 = 4; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + // Tag-delimited aggregate. + // Group type is deprecated and not supported after google.protobuf. However, Proto3 + // implementations should still be able to parse the group wire format and + // treat group fields as unknown fields. In Editions, the group wire format + // can be enabled via the `message_encoding` feature. + TYPE_GROUP = 10; + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + } + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REPEATED = 3; + // The required label is only allowed in google.protobuf. In proto3 and Editions + // it's explicitly prohibited. In Editions, the `field_presence` feature + // can be used to get this behavior. + LABEL_REQUIRED = 2; + } + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + optional string default_value = 7; + + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. + optional int32 oneof_index = 9; + + // JSON name of this field. The value is set by protocol compiler. If the + // user has set a "json_name" option on this field, that option's value + // will be used. Otherwise, it's deduced from the field's name by converting + // it to camelCase. + optional string json_name = 10; + + optional FieldOptions options = 8; + + // If true, this is a proto3 "optional". When a proto3 field is optional, it + // tracks presence regardless of field type. + // + // When proto3_optional is true, this field must belong to a oneof to signal + // to old proto3 clients that presence is tracked for this field. This oneof + // is known as a "synthetic" oneof, and this field must be its sole member + // (each proto3 optional field gets its own synthetic oneof). Synthetic oneofs + // exist in the descriptor only, and do not generate any API. Synthetic oneofs + // must be ordered after all "real" oneofs. + // + // For message fields, proto3_optional doesn't create any semantic change, + // since non-repeated message fields always track presence. However it still + // indicates the semantic detail of whether the user wrote "optional" or not. + // This can be useful for round-tripping the .proto file. For consistency we + // give message fields a synthetic oneof also, even though it is not required + // to track presence. This is especially important because the parser can't + // tell if a field is a message or an enum, so it must always create a + // synthetic oneof. + // + // Proto2 optional fields do not set this flag, because they already indicate + // optional with `LABEL_OPTIONAL`. + optional bool proto3_optional = 17; +} + +// Describes a oneof. +message OneofDescriptorProto { + optional string name = 1; + optional OneofOptions options = 2; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; + + // Range of reserved numeric values. Reserved values may not be used by + // entries in the same enum. Reserved ranges may not overlap. + // + // Note that this is distinct from DescriptorProto.ReservedRange in that it + // is inclusive such that it can appropriately represent the entire int32 + // domain. + message EnumReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Inclusive. + } + + // Range of reserved numeric values. Reserved numeric values may not be used + // by enum values in the same enum declaration. Reserved ranges may not + // overlap. + repeated EnumReservedRange reserved_range = 4; + + // Reserved enum value names, which may not be reused. A given name may only + // be reserved once. + repeated string reserved_name = 5; + + // Support for `export` and `local` keywords on enums. + optional SymbolVisibility visibility = 6; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; + + reserved 4; + reserved "stream"; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; + + // Identifies if client streams multiple client messages + optional bool client_streaming = 5 [default = false]; + // Identifies if server streams multiple server messages + optional bool server_streaming = 6 [default = false]; +} + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail protobuf-global-extension-registry@google.com +// to reserve extension numbers. Simply provide your project name (e.g. +// Objective-C plugin) and your project website (if available) -- there's no +// need to explain how you intend to use them. Usually you only need one +// extension number. You can declare multiple options with only one extension +// number by putting them in a sub-message. See the Custom Options section of +// the docs for examples: +// https://developers.google.com/protocol-buffers/docs/proto#options +// If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + // Controls the name of the wrapper Java class generated for the .proto file. + // That class will always contain the .proto file's getDescriptor() method as + // well as any top-level extensions defined in the .proto file. + // If java_multiple_files is disabled, then all the other classes from the + // .proto file will be nested inside the single wrapper outer class. + optional string java_outer_classname = 8; + + // If enabled, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the wrapper class + // named by java_outer_classname. However, the wrapper class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [ + default = false, + feature_support = { + edition_introduced: EDITION_PROTO2 + edition_removed: EDITION_2024 + removal_error: "This behavior is enabled by default in editions 2024 and above. " + "To disable it, you can set `features.(pb.java).nest_in_file_class = YES` " + "on individual messages, enums, or services." + + } + ]; + + // This option does nothing. + optional bool java_generate_equals_and_hash = 20 [deprecated=true]; + + // A proto2 file can set this to true to opt in to UTF-8 checking for Java, + // which will throw an exception if invalid UTF-8 is parsed from the wire or + // assigned to a string field. + // + // TODO: clarify exactly what kinds of field types this option + // applies to, and update these docs accordingly. + // + // Proto3 files already perform these checks. Setting the option explicitly to + // false has no effect: it cannot be used to opt proto3 files out of UTF-8 + // checks. + optional bool java_string_check_utf8 = 27 [default = false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default = SPEED]; + + // Sets the Go package where structs generated from this .proto will be + // placed. If omitted, the Go package will be derived from the following: + // - The basename of the package import path, if provided. + // - Otherwise, the package statement in the .proto file, if present. + // - Otherwise, the basename of the .proto file, without extension. + optional string go_package = 11; + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of google.protobuf. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default = false]; + optional bool java_generic_services = 17 [default = false]; + optional bool py_generic_services = 18 [default = false]; + reserved 42; // removed php_generic_services + reserved "php_generic_services"; + + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + optional bool deprecated = 23 [default = false]; + + // Enables the use of arenas for the proto messages in this file. This applies + // only to generated classes for C++. + optional bool cc_enable_arenas = 31 [default = true]; + + // Sets the objective c class prefix which is prepended to all objective c + // generated classes from this .proto. There is no default. + optional string objc_class_prefix = 36; + + // Namespace for generated classes; defaults to the package. + optional string csharp_namespace = 37; + + // By default Swift generators will take the proto package and CamelCase it + // replacing '.' with underscore and use that to prefix the types/symbols + // defined. When this options is provided, they will use this value instead + // to prefix the types/symbols defined. + optional string swift_prefix = 39; + + // Sets the php class prefix which is prepended to all php generated classes + // from this .proto. Default is empty. + optional string php_class_prefix = 40; + + // Use this option to change the namespace of php generated classes. Default + // is empty. When this option is empty, the package name will be used for + // determining the namespace. + optional string php_namespace = 41; + + // Use this option to change the namespace of php generated metadata classes. + // Default is empty. When this option is empty, the proto file name will be + // used for determining the namespace. + optional string php_metadata_namespace = 44; + + // Use this option to change the package of ruby generated classes. Default + // is empty. When this option is not set, the package name will be used for + // determining the ruby package. + optional string ruby_package = 45; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 50; + + // The parser stores options it doesn't recognize here. + // See the documentation for the "Options" section above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. + // See the documentation for the "Options" section above. + extensions 1000 to max; + + reserved 38; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default = false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default = false]; + + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default = false]; + + reserved 4, 5, 6; + + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementations still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + optional bool map_entry = 7; + + reserved 8; // javalite_serializable + reserved 9; // javanano_as_lite + + // Enable the legacy handling of JSON field name conflicts. This lowercases + // and strips underscored from the fields before comparison in proto3 only. + // The new behavior takes `json_name` into account and applies to proto2 as + // well. + // + // This should only be used as a temporary measure against broken builds due + // to the change in behavior for JSON field name conflicts. + // + // TODO This is legacy behavior we plan to remove once downstream + // teams have had time to migrate. + optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated = true]; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 12; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is only implemented to support use of + // [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of + // type "bytes" in the open source release. + // TODO: make ctype actually deprecated. + optional CType ctype = 1 [/*deprecated = true,*/ default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + // The option [ctype=CORD] may be applied to a non-repeated field of type + // "bytes". It indicates that in C++, the data should be stored in a Cord + // instead of a string. For very large strings, this may reduce memory + // fragmentation. It may also allow better performance when parsing from a + // Cord, or when parsing with aliasing enabled, as the parsed Cord may then + // alias the original buffer. + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. In proto3, only explicit setting it to + // false will avoid using packed encoding. This option is prohibited in + // Editions, but the `repeated_field_encoding` feature can be used to control + // the behavior. + optional bool packed = 2; + + // The jstype option determines the JavaScript type used for values of the + // field. The option is permitted only for 64 bit integral and fixed types + // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + // is represented as JavaScript string, which avoids loss of precision that + // can happen when a large value is converted to a floating point JavaScript. + // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + // use the JavaScript "number" type. The behavior of the default option + // JS_NORMAL is implementation dependent. + // + // This option is an enum to permit additional types to be added, e.g. + // goog.math.Integer. + optional JSType jstype = 6 [default = JS_NORMAL]; + enum JSType { + // Use the default type. + JS_NORMAL = 0; + + // Use JavaScript strings. + JS_STRING = 1; + + // Use JavaScript numbers. + JS_NUMBER = 2; + } + + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // Note that lazy message fields are still eagerly verified to check + // ill-formed wireformat or missing required fields. Calling IsInitialized() + // on the outer message would fail if the inner message has missing required + // fields. Failed verification would result in parsing failure (except when + // uninitialized messages are acceptable). + optional bool lazy = 5 [default = false]; + + // unverified_lazy does no correctness checks on the byte stream. This should + // only be used where lazy with verification is prohibitive for performance + // reasons. + optional bool unverified_lazy = 15 [default = false]; + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default = false]; + + // DEPRECATED. DO NOT USE! + // For Google-internal migration only. Do not use. + optional bool weak = 10 [default = false, deprecated = true]; + + // Indicate that the field value should not be printed out when using debug + // formats, e.g. when the field contains sensitive credentials. + optional bool debug_redact = 16 [default = false]; + + // If set to RETENTION_SOURCE, the option will be omitted from the binary. + enum OptionRetention { + RETENTION_UNKNOWN = 0; + RETENTION_RUNTIME = 1; + RETENTION_SOURCE = 2; + } + + optional OptionRetention retention = 17; + + // This indicates the types of entities that the field may apply to when used + // as an option. If it is unset, then the field may be freely used as an + // option on any kind of entity. + enum OptionTargetType { + TARGET_TYPE_UNKNOWN = 0; + TARGET_TYPE_FILE = 1; + TARGET_TYPE_EXTENSION_RANGE = 2; + TARGET_TYPE_MESSAGE = 3; + TARGET_TYPE_FIELD = 4; + TARGET_TYPE_ONEOF = 5; + TARGET_TYPE_ENUM = 6; + TARGET_TYPE_ENUM_ENTRY = 7; + TARGET_TYPE_SERVICE = 8; + TARGET_TYPE_METHOD = 9; + } + + repeated OptionTargetType targets = 19; + + message EditionDefault { + optional Edition edition = 3; + optional string value = 2; // Textproto value. + } + repeated EditionDefault edition_defaults = 20; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 21; + + // Information about the support window of a feature. + message FeatureSupport { + // The edition that this feature was first available in. In editions + // earlier than this one, the default assigned to EDITION_LEGACY will be + // used, and proto files will not be able to override it. + optional Edition edition_introduced = 1; + + // The edition this feature becomes deprecated in. Using this after this + // edition may trigger warnings. + optional Edition edition_deprecated = 2; + + // The deprecation warning text if this feature is used after the edition it + // was marked deprecated in. + optional string deprecation_warning = 3; + + // The edition this feature is no longer available in. In editions after + // this one, the last default assigned will be used, and proto files will + // not be able to override it. + optional Edition edition_removed = 4; + + // The removal error text if this feature is used after the edition it was + // removed in. + optional string removal_error = 5; + } + optional FeatureSupport feature_support = 22; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; + + reserved 4; // removed jtype + reserved 18; // reserve target, target_obsolete_do_not_use +} + +message OneofOptions { + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 1; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // Set this option to true to allow mapping different tag names to the same + // value. + optional bool allow_alias = 2; + + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + optional bool deprecated = 3 [default = false]; + + reserved 5; // javanano_as_lite + + // Enable the legacy handling of JSON field name conflicts. This lowercases + // and strips underscored from the fields before comparison in proto3 only. + // The new behavior takes `json_name` into account and applies to proto2 as + // well. + // TODO Remove this legacy behavior once downstream teams have + // had time to migrate. + optional bool deprecated_legacy_json_field_conflicts = 6 [deprecated = true]; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 7; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + optional bool deprecated = 1 [default = false]; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 2; + + // Indicate that fields annotated with this enum value should not be printed + // out when using debug formats, e.g. when the field contains sensitive + // credentials. + optional bool debug_redact = 3 [default = false]; + + // Information about the support window of a feature value. + optional FieldOptions.FeatureSupport feature_support = 4; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 34; + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + optional bool deprecated = 33 [default = false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + optional bool deprecated = 33 [default = false]; + + // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + // or neither? HTTP based RPC implementation may choose GET verb for safe + // methods, and PUT verb for idempotent methods instead of the default POST. + enum IdempotencyLevel { + IDEMPOTENCY_UNKNOWN = 0; + NO_SIDE_EFFECTS = 1; // implies idempotent + IDEMPOTENT = 2; // idempotent, but may have side effects + } + optional IdempotencyLevel idempotency_level = 34 + [default = IDEMPOTENCY_UNKNOWN]; + + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 35; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents + // "foo.(bar.baz).moo". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Features + +// TODO Enums in C++ gencode (and potentially other languages) are +// not well scoped. This means that each of the feature enums below can clash +// with each other. The short names we've chosen maximize call-site +// readability, but leave us very open to this scenario. A future feature will +// be designed and implemented to handle this, hopefully before we ever hit a +// conflict here. +message FeatureSet { + enum FieldPresence { + FIELD_PRESENCE_UNKNOWN = 0; + EXPLICIT = 1; + IMPLICIT = 2; + LEGACY_REQUIRED = 3; + } + optional FieldPresence field_presence = 1 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPLICIT" }, + edition_defaults = { edition: EDITION_PROTO3, value: "IMPLICIT" }, + edition_defaults = { edition: EDITION_2023, value: "EXPLICIT" } + ]; + + enum EnumType { + ENUM_TYPE_UNKNOWN = 0; + OPEN = 1; + CLOSED = 2; + } + optional EnumType enum_type = 2 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "CLOSED" }, + edition_defaults = { edition: EDITION_PROTO3, value: "OPEN" } + ]; + + enum RepeatedFieldEncoding { + REPEATED_FIELD_ENCODING_UNKNOWN = 0; + PACKED = 1; + EXPANDED = 2; + } + optional RepeatedFieldEncoding repeated_field_encoding = 3 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPANDED" }, + edition_defaults = { edition: EDITION_PROTO3, value: "PACKED" } + ]; + + enum Utf8Validation { + UTF8_VALIDATION_UNKNOWN = 0; + VERIFY = 2; + NONE = 3; + reserved 1; + } + optional Utf8Validation utf8_validation = 4 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "NONE" }, + edition_defaults = { edition: EDITION_PROTO3, value: "VERIFY" } + ]; + + enum MessageEncoding { + MESSAGE_ENCODING_UNKNOWN = 0; + LENGTH_PREFIXED = 1; + DELIMITED = 2; + } + optional MessageEncoding message_encoding = 5 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "LENGTH_PREFIXED" } + ]; + + enum JsonFormat { + JSON_FORMAT_UNKNOWN = 0; + ALLOW = 1; + LEGACY_BEST_EFFORT = 2; + } + optional JsonFormat json_format = 6 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "LEGACY_BEST_EFFORT" }, + edition_defaults = { edition: EDITION_PROTO3, value: "ALLOW" } + ]; + + enum EnforceNamingStyle { + ENFORCE_NAMING_STYLE_UNKNOWN = 0; + STYLE2024 = 1; + STYLE_LEGACY = 2; + } + optional EnforceNamingStyle enforce_naming_style = 7 [ + retention = RETENTION_SOURCE, + targets = TARGET_TYPE_FILE, + targets = TARGET_TYPE_EXTENSION_RANGE, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_ONEOF, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_ENUM_ENTRY, + targets = TARGET_TYPE_SERVICE, + targets = TARGET_TYPE_METHOD, + feature_support = { + edition_introduced: EDITION_2024, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "STYLE_LEGACY" }, + edition_defaults = { edition: EDITION_2024, value: "STYLE2024" } + ]; + + message VisibilityFeature { + enum DefaultSymbolVisibility { + DEFAULT_SYMBOL_VISIBILITY_UNKNOWN = 0; + + // Default pre-EDITION_2024, all UNSET visibility are export. + EXPORT_ALL = 1; + + // All top-level symbols default to export, nested default to local. + EXPORT_TOP_LEVEL = 2; + + // All symbols default to local. + LOCAL_ALL = 3; + + // All symbols local by default. Nested types cannot be exported. + // With special case caveat for message { enum {} reserved 1 to max; } + // This is the recommended setting for new protos. + STRICT = 4; + } + reserved 1 to max; + } + optional VisibilityFeature.DefaultSymbolVisibility default_symbol_visibility = + 8 [ + retention = RETENTION_SOURCE, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2024, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPORT_ALL" }, + edition_defaults = { edition: EDITION_2024, value: "EXPORT_TOP_LEVEL" } + ]; + + reserved 999; + + extensions 1000 to 9994 [ + declaration = { + number: 1000, + full_name: ".pb.cpp", + type: ".pb.CppFeatures" + }, + declaration = { + number: 1001, + full_name: ".pb.java", + type: ".pb.JavaFeatures" + }, + declaration = { number: 1002, full_name: ".pb.go", type: ".pb.GoFeatures" }, + declaration = { + number: 1003, + full_name: ".pb.python", + type: ".pb.PythonFeatures" + }, + declaration = { + number: 1100, + full_name: ".imp.impress_feature_set", + type: ".imp.ImpressFeatureSet" + }, + declaration = { + number: 9989, + full_name: ".pb.java_mutable", + type: ".pb.JavaMutableFeatures" + }, + declaration = { + number: 9990, + full_name: ".pb.proto1", + type: ".pb.Proto1Features" + } + ]; + + extensions 9995 to 9999; // For internal testing + extensions 10000; // for https://github.com/bufbuild/protobuf-es +} + +// A compiled specification for the defaults of a set of features. These +// messages are generated from FeatureSet extensions and can be used to seed +// feature resolution. The resolution with this object becomes a simple search +// for the closest matching edition, followed by proto merges. +message FeatureSetDefaults { + // A map from every known edition with a unique set of defaults to its + // defaults. Not all editions may be contained here. For a given edition, + // the defaults at the closest matching edition ordered at or before it should + // be used. This field must be in strict ascending order by edition. + message FeatureSetEditionDefault { + optional Edition edition = 3; + + // Defaults of features that can be overridden in this edition. + optional FeatureSet overridable_features = 4; + + // Defaults of features that can't be overridden in this edition. + optional FeatureSet fixed_features = 5; + + reserved 1, 2; + reserved "features"; + } + repeated FeatureSetEditionDefault defaults = 1; + + // The minimum supported edition (inclusive) when this was constructed. + // Editions before this will not have defaults. + optional Edition minimum_edition = 4; + + // The maximum known edition (inclusive) when this was constructed. Editions + // after this will not have reliable defaults. + optional Edition maximum_edition = 5; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendant. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition appears. + // For example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed = true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed = true]; + + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // leading_detached_comments will keep paragraphs of comments that appear + // before (but not connected to) the current element. Each paragraph, + // separated by empty lines, will be one comment element in the repeated + // field. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to moo. + // // + // // Another line attached to moo. + // optional double moo = 4; + // + // // Detached comment for corge. This is not leading or trailing comments + // // to moo or corge because there are blank lines separating it from + // // both. + // + // // Detached comment for corge paragraph 2. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + // + // // ignored detached comments. + optional string leading_comments = 3; + optional string trailing_comments = 4; + repeated string leading_detached_comments = 6; + } + + // Extensions for tooling. + extensions 536000000 [declaration = { + number: 536000000 + type: ".buf.descriptor.v1.SourceCodeInfoExtension" + full_name: ".buf.descriptor.v1.buf_source_code_info_extension" + }]; +} + +// Describes the relationship between generated code and its original source +// file. A GeneratedCodeInfo message is associated with only one generated +// source file, but may contain references to different source .proto files. +message GeneratedCodeInfo { + // An Annotation connects some span of text in generated code to an element + // of its generating .proto file. + repeated Annotation annotation = 1; + message Annotation { + // Identifies the element in the original source .proto file. This field + // is formatted the same as SourceCodeInfo.Location.path. + repeated int32 path = 1 [packed = true]; + + // Identifies the filesystem path to the original source .proto. + optional string source_file = 2; + + // Identifies the starting offset in bytes in the generated code + // that relates to the identified object. + optional int32 begin = 3; + + // Identifies the ending offset in bytes in the generated code that + // relates to the identified object. The end offset should be one past + // the last relevant byte (so the length of the text = end - begin). + optional int32 end = 4; + + // Represents the identified object's effect on the element in the original + // .proto file. + enum Semantic { + // There is no effect or the effect is indescribable. + NONE = 0; + // The element is set or otherwise mutated. + SET = 1; + // An alias to the element is returned. + ALIAS = 2; + } + optional Semantic semantic = 5; + } +} + +// Describes the 'visibility' of a symbol with respect to the proto import +// system. Symbols can only be imported when the visibility rules do not prevent +// it (ex: local symbols cannot be imported). Visibility modifiers can only set +// on `message` and `enum` as they are the only types available to be referenced +// from other files. +enum SymbolVisibility { + VISIBILITY_UNSET = 0; + VISIBILITY_LOCAL = 1; + VISIBILITY_EXPORT = 2; +} diff --git a/Public/Proto/ServerInternal/sources/service_user.proto b/Public/Proto/ServerInternal/sources/service_user.proto new file mode 100644 index 0000000..7a959d1 --- /dev/null +++ b/Public/Proto/ServerInternal/sources/service_user.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; + +option go_package = "common/proto/ss/grpc_pb"; +import "ss_common.proto"; +import "google/api/annotations.proto"; + +service User { + rpc Login(LoginReq) returns (LoginResp) { + option (google.api.http) = { + post: "/user/login" + body: "*" + }; + } +} + +message LoginReq { + string Phone = 1 [json_name = "phone"]; // 手机号 + string Code = 2 [json_name = "code"]; // 验证码 +} + +message LoginResp { + int32 UID = 1 [json_name = "uid"]; // 用户ID +} \ No newline at end of file diff --git a/Public/Proto/ServerInternal/sources/ss_common.proto b/Public/Proto/ServerInternal/sources/ss_common.proto index 87c4fc5..501aea1 100644 --- a/Public/Proto/ServerInternal/sources/ss_common.proto +++ b/Public/Proto/ServerInternal/sources/ss_common.proto @@ -1,3 +1,8 @@ syntax = "proto3"; -option go_package = "common/proto/ss/ss_common"; \ No newline at end of file +option go_package = "common/proto/ss/ss_common"; + +message ErrorInfo { + int32 code = 1; + string msg = 2; +} \ No newline at end of file diff --git a/Public/Tools/mysql_model/gen.ps1 b/Public/Tools/mysql_model/gen.ps1 new file mode 100644 index 0000000..a3a76c1 --- /dev/null +++ b/Public/Tools/mysql_model/gen.ps1 @@ -0,0 +1,16 @@ +# gen.ps1 - 极简版 +& .\gentool.exe ` +-dsn "root:gR9pV4tY7zR6qL3e@tcp(47.108.184.184:3306)/user_db?charset=utf8mb4&parseTime=True&loc=Local" ` +-fieldSignable ` +-outPath "./user_db/query" + +Get-ChildItem ./user_db/model/*.gen.go | ForEach-Object { + $c = Get-Content $_.FullName -Raw -Encoding UTF8 + if ($c -match '\bSn\s+int64\b' -and $c -notmatch 'BeforeCreate') { + $c -match 'type\s+(\w+)\s+struct' | Out-Null + $n = $matches[1] + $c = $c -replace '(?s)(import\s*\([^)]*)', "`$1`t`"common/utils`"`n" + $hook = "`n`n// auto sn`nfunc (m *$n) BeforeCreate(_ *gorm.DB) error {`n`tif m.Sn == 0 {`n`t`tm.Sn = utils.SnowflakeInstance().Generate().Int64()`n`t}`n`treturn nil`n}" + Set-Content $_.FullName ($c.TrimEnd() + $hook) -Encoding UTF8 + } +} \ No newline at end of file diff --git a/Public/Tools/mysql_model/gen_model.bat b/Public/Tools/mysql_model/gen_model.bat deleted file mode 100644 index e793479..0000000 --- a/Public/Tools/mysql_model/gen_model.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off - -gentool ^ --dsn "root:gR9pV4tY7zR6qL3e@tcp(47.108.184.184:3306)/point?charset=utf8mb4&parseTime=True&loc=Local" ^ --fieldSignable \ No newline at end of file diff --git a/Server/common/db/mysql/point/model/users.gen.go b/Public/Tools/mysql_model/user_db/model/users.gen.go similarity index 62% rename from Server/common/db/mysql/point/model/users.gen.go rename to Public/Tools/mysql_model/user_db/model/users.gen.go index de2bc63..548d913 100644 --- a/Server/common/db/mysql/point/model/users.gen.go +++ b/Public/Tools/mysql_model/user_db/model/users.gen.go @@ -1,4 +1,4 @@ -// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. // Code generated by gorm.io/gen. DO NOT EDIT. // Code generated by gorm.io/gen. DO NOT EDIT. @@ -8,15 +8,17 @@ import ( "time" "gorm.io/gorm" + "common/utils" ) const TableNameUser = "users" // User mapped from table type User struct { - ID int64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` - Sn string `gorm:"column:sn;not null;comment:业务唯一编号" json:"sn"` // 业务唯一编号 + ID uint64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` + Sn int64 `gorm:"column:sn;not null;comment:业务唯一编号" json:"sn"` // 业务唯一编号 Name string `gorm:"column:name;not null" json:"name"` + Phone string `gorm:"column:phone;not null" json:"phone"` CreatedAt time.Time `gorm:"column:created_at;not null" json:"created_at"` UpdatedAt time.Time `gorm:"column:updated_at;not null" json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"column:deleted_at" json:"deleted_at"` @@ -26,3 +28,11 @@ type User struct { func (*User) TableName() string { return TableNameUser } + +// auto sn +func (m *User) BeforeCreate(_ *gorm.DB) error { + if m.Sn == 0 { + m.Sn = utils.SnowflakeInstance().Generate().Int64() + } + return nil +} diff --git a/Public/Tools/mysql_model/dao/query/gen.go b/Public/Tools/mysql_model/user_db/query/gen.go similarity index 100% rename from Public/Tools/mysql_model/dao/query/gen.go rename to Public/Tools/mysql_model/user_db/query/gen.go diff --git a/Public/Tools/mysql_model/dao/query/users.gen.go b/Public/Tools/mysql_model/user_db/query/users.gen.go similarity index 94% rename from Public/Tools/mysql_model/dao/query/users.gen.go rename to Public/Tools/mysql_model/user_db/query/users.gen.go index ce51dee..eba891f 100644 --- a/Public/Tools/mysql_model/dao/query/users.gen.go +++ b/Public/Tools/mysql_model/user_db/query/users.gen.go @@ -25,9 +25,10 @@ func newUser(db *gorm.DB, opts ...gen.DOOption) user { tableName := _user.userDo.TableName() _user.ALL = field.NewAsterisk(tableName) - _user.ID = field.NewInt64(tableName, "id") - _user.Sn = field.NewString(tableName, "sn") + _user.ID = field.NewUint64(tableName, "id") + _user.Sn = field.NewInt64(tableName, "sn") _user.Name = field.NewString(tableName, "name") + _user.Phone = field.NewString(tableName, "phone") _user.CreatedAt = field.NewTime(tableName, "created_at") _user.UpdatedAt = field.NewTime(tableName, "updated_at") _user.DeletedAt = field.NewField(tableName, "deleted_at") @@ -41,9 +42,10 @@ type user struct { userDo userDo ALL field.Asterisk - ID field.Int64 - Sn field.String // 业务唯一编号 + ID field.Uint64 + Sn field.Int64 // 业务唯一编号 Name field.String + Phone field.String CreatedAt field.Time UpdatedAt field.Time DeletedAt field.Field @@ -63,9 +65,10 @@ func (u user) As(alias string) *user { func (u *user) updateTableName(table string) *user { u.ALL = field.NewAsterisk(table) - u.ID = field.NewInt64(table, "id") - u.Sn = field.NewString(table, "sn") + u.ID = field.NewUint64(table, "id") + u.Sn = field.NewInt64(table, "sn") u.Name = field.NewString(table, "name") + u.Phone = field.NewString(table, "phone") u.CreatedAt = field.NewTime(table, "created_at") u.UpdatedAt = field.NewTime(table, "updated_at") u.DeletedAt = field.NewField(table, "deleted_at") @@ -93,10 +96,11 @@ func (u *user) GetFieldByName(fieldName string) (field.OrderExpr, bool) { } func (u *user) fillFieldMap() { - u.fieldMap = make(map[string]field.Expr, 6) + u.fieldMap = make(map[string]field.Expr, 7) u.fieldMap["id"] = u.ID u.fieldMap["sn"] = u.Sn u.fieldMap["name"] = u.Name + u.fieldMap["phone"] = u.Phone u.fieldMap["created_at"] = u.CreatedAt u.fieldMap["updated_at"] = u.UpdatedAt u.fieldMap["deleted_at"] = u.DeletedAt diff --git a/Public/Tools/tidy.bat b/Public/Tools/tidy.bat index 9e8dc6e..79a6e68 100644 --- a/Public/Tools/tidy.bat +++ b/Public/Tools/tidy.bat @@ -10,4 +10,7 @@ go mod tidy cd ../scene go mod tidy +cd ../user +go mod tidy + Pause \ No newline at end of file diff --git a/Server/common/db/mysql/client.go b/Server/common/db/mysql/client.go index 48aa04e..aad686d 100644 --- a/Server/common/db/mysql/client.go +++ b/Server/common/db/mysql/client.go @@ -2,9 +2,7 @@ package mysql import ( "common/config" - pointQuery "common/db/mysql/point/query" "common/log" - "database/sql" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" @@ -13,23 +11,14 @@ import ( type DBName string -const ( - DBNamePoint DBName = "point" -) - -var dbs = make(map[DBName]*sql.DB) -var queryS = make(map[DBName]interface{}) +var dbs = make(map[DBName]*gorm.DB) func Init(cfg map[string]*config.MySQLConfig) error { for name, oneConfig := range cfg { - switch DBName(name) { - case DBNamePoint: - if db, err := initOneDB(oneConfig); err != nil { - return err - } else { - dbs[DBNamePoint], _ = db.DB() - queryS[DBNamePoint] = pointQuery.Use(db) - } + if db, err := initOneDB(oneConfig); err != nil { + return err + } else { + dbs[DBName(name)] = db } } return nil @@ -73,15 +62,12 @@ func parseLogLevel(logLevel string) logger.LogLevel { return logger.Info } -func GetPointDB() *pointQuery.Query { - return getQuery[*pointQuery.Query](DBNamePoint) -} - -func getQuery[T any](dbName DBName) (result T) { - if q, ok := queryS[dbName]; ok { - result, _ = q.(T) +func GetDB(dbName DBName) *gorm.DB { + if q, ok := dbs[dbName]; ok { + return q } - return + log.Errorf("db %s not found", dbName) + return nil } func Close() error { @@ -89,8 +75,10 @@ func Close() error { return nil } for name, db := range dbs { - if err := db.Close(); err != nil { - log.Errorf("close db %s error: %v", name, err) + if sqlDB, _ := db.DB(); sqlDB != nil { + if err := sqlDB.Close(); err != nil { + log.Errorf("close db %s error: %v", name, err) + } } } return nil diff --git a/Server/common/discover/common/define.go b/Server/common/discover/common/define.go index 54732e7..1254f89 100644 --- a/Server/common/discover/common/define.go +++ b/Server/common/discover/common/define.go @@ -16,9 +16,15 @@ var ( ) var ( - KeyDiscoverGateway = KeyDiscoverService + "/gateway" // 网关服 - KeyDiscoverDatabase = KeyDiscoverService + "/database" // 数据服 - KeyDiscoverScene = KeyDiscoverService + "/scene" // 场景服 + KeyDiscoverServiceNameGateway = "gateway" // 网关服 + KeyDiscoverServiceNameScene = "scene" // 场景服 + KeyDiscoverServiceNameUser = "user" // 用户中心 +) + +var ( + KeyDiscoverGateway = KeyDiscoverService + "/" + KeyDiscoverServiceNameGateway // 网关服 + KeyDiscoverScene = KeyDiscoverService + "/" + KeyDiscoverServiceNameScene // 场景服 + KeyDiscoverUser = KeyDiscoverService + "/" + KeyDiscoverServiceNameUser // 用户中心 ) // ServiceProvider 服务提供者 diff --git a/Server/common/go.mod b/Server/common/go.mod index 06d0cf7..b90cdf2 100644 --- a/Server/common/go.mod +++ b/Server/common/go.mod @@ -5,6 +5,7 @@ go 1.23.1 require ( github.com/bwmarrin/snowflake v0.3.0 github.com/gobwas/ws v1.4.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 github.com/natefinch/lumberjack v2.0.0+incompatible github.com/panjf2000/gnet/v2 v2.9.1 github.com/redis/go-redis/v9 v9.10.0 @@ -12,6 +13,7 @@ require ( go.etcd.io/etcd/api/v3 v3.6.1 go.etcd.io/etcd/client/v3 v3.6.1 go.uber.org/zap v1.27.0 + google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb google.golang.org/grpc v1.71.1 google.golang.org/protobuf v1.36.5 gorm.io/driver/mysql v1.6.0 @@ -35,7 +37,6 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/panjf2000/ants/v2 v2.11.3 // indirect @@ -56,7 +57,6 @@ require ( golang.org/x/sys v0.34.0 // indirect golang.org/x/text v0.28.0 // indirect golang.org/x/tools v0.35.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/Server/common/net/grpc/grpc_conn/conn.go b/Server/common/net/grpc/grpc_conn/conn.go index 7f0c701..f68a88f 100644 --- a/Server/common/net/grpc/grpc_conn/conn.go +++ b/Server/common/net/grpc/grpc_conn/conn.go @@ -3,6 +3,7 @@ package grpc_conn import ( "common/log" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/keepalive" "time" ) @@ -18,7 +19,7 @@ func NewGrpcConnection(sid int64, address string) (*GrpcConnection, error) { } conn, err := grpc.NewClient( address, - grpc.WithInsecure(), + grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithKeepaliveParams( keepalive.ClientParameters{ Time: 30 * time.Second, // 保活探测包发送的时间间隔 diff --git a/Server/common/net/grpc/grpc_conn/stats.go b/Server/common/net/grpc/grpc_conn/stats.go deleted file mode 100644 index 0e6449e..0000000 --- a/Server/common/net/grpc/grpc_conn/stats.go +++ /dev/null @@ -1,45 +0,0 @@ -package grpc_conn - -import ( - "context" - "fmt" - "google.golang.org/grpc/stats" -) - -// 1. 实现 stats.Handler 接口 -type StatsHandler struct{} - -func (h *StatsHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context { - // 给 RPC 调用打标签(例如记录方法名) - return context.WithValue(ctx, "rpc_method", info.FullMethodName) -} - -func (h *StatsHandler) HandleRPC(ctx context.Context, s stats.RPCStats) { - // 处理 RPC 统计信息 - switch t := s.(type) { - case *stats.Begin: - fmt.Printf("RPC started: %s\n", ctx.Value("rpc_method")) - case *stats.End: - fmt.Printf("RPC finished: %s (duration: %v)\n", - ctx.Value("rpc_method"), t.EndTime.Sub(t.BeginTime)) - case *stats.InPayload: - fmt.Printf("Received %d bytes\n", t.WireLength) - case *stats.OutPayload: - fmt.Printf("Sent %d bytes\n", t.WireLength) - } -} - -func (h *StatsHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context { - // 给连接打标签 - return ctx -} - -func (h *StatsHandler) HandleConn(ctx context.Context, s stats.ConnStats) { - // 处理连接事件 - switch s.(type) { - case *stats.ConnBegin: - fmt.Println("Connection established") - case *stats.ConnEnd: - fmt.Println("Connection closed") - } -} diff --git a/Server/common/net/grpc/resolver/conn.go b/Server/common/net/grpc/resolver/conn.go new file mode 100644 index 0000000..b9a97a9 --- /dev/null +++ b/Server/common/net/grpc/resolver/conn.go @@ -0,0 +1,30 @@ +package resolver + +import ( + "common/log" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/keepalive" + "time" +) + +func NewGrpcConnection(target string) (*grpc.ClientConn, error) { + cc, err := grpc.NewClient( + target, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithDefaultServiceConfig(`{"loadBalancingConfig": [{"round_robin": {}}]}`), + grpc.WithKeepaliveParams( + keepalive.ClientParameters{ + Time: 30 * time.Second, // 保活探测包发送的时间间隔 + Timeout: 10 * time.Second, // 保活探测包的超时时间 + PermitWithoutStream: true, + }, + ), + //grpc.WithStatsHandler(&StatsHandler{}), + ) + if err != nil { + log.Errorf("create grpc err: %v, target: %v", err, target) + return nil, err + } + return cc, nil +} diff --git a/Server/common/net/grpc/resolver/etcd_resolver.go b/Server/common/net/grpc/resolver/etcd_resolver.go new file mode 100644 index 0000000..40bdcec --- /dev/null +++ b/Server/common/net/grpc/resolver/etcd_resolver.go @@ -0,0 +1,84 @@ +package resolver + +import ( + "common/db/etcd" + "common/discover/common" + "common/log" + "context" + "go.etcd.io/etcd/client/v3" + "google.golang.org/grpc/resolver" + "strings" +) + +const etcdSchema = "etcd" + +func init() { + resolver.Register(&etcdBuilder{}) +} + +type etcdBuilder struct{} + +func (*etcdBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { + serviceName := strings.TrimPrefix(target.URL.Path, "/") + r := &etcdResolver{ + serviceName: serviceName, + cc: cc, + } + r.start() + return r, nil +} + +func (*etcdBuilder) Scheme() string { return etcdSchema } + +type etcdResolver struct { + serviceName string + cc resolver.ClientConn + ctx context.Context + cancel context.CancelFunc +} + +func (r *etcdResolver) start() { + r.ctx, r.cancel = context.WithCancel(context.Background()) + r.update() + go r.watch() +} + +func (r *etcdResolver) getPrefix() string { + return common.KeyDiscoverService + "/" + r.serviceName +} + +func (r *etcdResolver) update() { + resp, err := etcd.GetClient().Get(r.getPrefix(), clientv3.WithPrefix()) + if err != nil { + log.Errorf("etcd resolver get error: %v", err) + return + } + + var addrArray []resolver.Address + for _, kv := range resp.Kvs { + addr := string(kv.Value) + if addr != "" { + addrArray = append(addrArray, resolver.Address{Addr: addr}) + } + } + + _ = r.cc.UpdateState(resolver.State{Addresses: addrArray}) +} + +func (r *etcdResolver) watch() { + watchCh := etcd.GetClient().Watch(r.getPrefix(), clientv3.WithPrefix()) + for w := range watchCh { + if w.Err() != nil { + continue + } + r.update() + } +} + +func (r *etcdResolver) ResolveNow(resolver.ResolveNowOptions) { + r.update() +} + +func (r *etcdResolver) Close() { + r.cancel() +} diff --git a/Server/common/net/grpc/resolver/resolver_mgr.go b/Server/common/net/grpc/resolver/resolver_mgr.go new file mode 100644 index 0000000..d2371b2 --- /dev/null +++ b/Server/common/net/grpc/resolver/resolver_mgr.go @@ -0,0 +1,35 @@ +package resolver + +import ( + "google.golang.org/grpc" + "sync" +) + +var ( + mu = sync.RWMutex{} + conn = make(map[string]*grpc.ClientConn) +) + +func GetGrpcClientConn(target string) (*grpc.ClientConn, error) { + mu.RLock() + if c, ok := conn[target]; ok && c != nil { + mu.RUnlock() + return c, nil + } + mu.RUnlock() + + mu.Lock() + defer mu.Unlock() + + if c, ok := conn[target]; ok && c != nil { + return c, nil + } + + newConn, err := NewGrpcConnection(target) + if err != nil { + return nil, err + } + + conn[target] = newConn + return newConn, nil +} diff --git a/Server/common/net/grpc/service/client_scene.go b/Server/common/net/grpc/service/client_scene.go index 02a9417..b7df99c 100644 --- a/Server/common/net/grpc/service/client_scene.go +++ b/Server/common/net/grpc/service/client_scene.go @@ -3,6 +3,7 @@ package service import ( "common/discover" "common/discover/common" + "common/net/grpc/resolver" "common/proto/ss/grpc_pb" ) @@ -14,6 +15,14 @@ func SceneNewClient(sid ...int64) (grpc_pb.SceneClient, error) { return grpc_pb.NewSceneClient(c), nil } +func SceneNewClientLB() (grpc_pb.SceneClient, error) { + c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameScene) + if err != nil { + return nil, err + } + return grpc_pb.NewSceneClient(c), nil +} + func SceneNewBroadcastClient() map[int64]grpc_pb.SceneClient { clientM := make(map[int64]grpc_pb.SceneClient) connM := discover.FindServerAll(common.KeyDiscoverScene) diff --git a/Server/common/net/grpc/service/client_user.go b/Server/common/net/grpc/service/client_user.go new file mode 100644 index 0000000..fd470bb --- /dev/null +++ b/Server/common/net/grpc/service/client_user.go @@ -0,0 +1,24 @@ +package service + +import ( + "common/discover" + "common/discover/common" + "common/net/grpc/resolver" + "common/proto/ss/grpc_pb" +) + +func UserNewClient(sid ...int64) (grpc_pb.UserClient, error) { + c, err := discover.FindServer(common.KeyDiscoverUser, sid...) + if err != nil { + return nil, err + } + return grpc_pb.NewUserClient(c), nil +} + +func UserNewClientLB() (grpc_pb.UserClient, error) { + c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameUser) + if err != nil { + return nil, err + } + return grpc_pb.NewUserClient(c), nil +} diff --git a/Server/common/net/grpc/service/service.go b/Server/common/net/grpc/service/service.go index 4488df9..8c9e4d8 100644 --- a/Server/common/net/grpc/service/service.go +++ b/Server/common/net/grpc/service/service.go @@ -7,7 +7,9 @@ import ( "context" "fmt" "google.golang.org/grpc" + "google.golang.org/grpc/codes" "google.golang.org/grpc/keepalive" + "google.golang.org/grpc/status" "net" "sync" "time" @@ -51,6 +53,7 @@ func (s *Base) Init(addr string, port int32) { defer func() { if r := recover(); r != nil { log.Errorf("server Panic: %v", r) + err = status.Error(codes.Internal, fmt.Sprintf("%v", r)) } }() resp, err = handler(ctx, req) diff --git a/Server/common/net/http/http_resp/code.go b/Server/common/net/http/http_resp/code.go new file mode 100644 index 0000000..ec29b5d --- /dev/null +++ b/Server/common/net/http/http_resp/code.go @@ -0,0 +1,46 @@ +package http_resp + +import ( + "common/proto/ss/ss_common" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +var ( + OK = NewCode(0, "OK") + Failed = NewCode(1, "Failed") + ParamError = NewCode(1001, "参数错误") + NameEmpty = NewCode(1002, "名称不能为空") + NameDuplicate = NewCode(1003, "名称或编号不能重复") + ListEmpty = NewCode(1004, "列表不能为空") + RepeatCommit = NewCode(1005, "请勿重复提交") +) + +type Code struct { + code int + error string +} + +func NewCode(code int, error string) *Code { + return &Code{ + code: code, + error: error, + } +} + +func (c *Code) Code() int { + return c.code +} + +func (c *Code) Error() string { + return c.error +} + +func (c *Code) Wrap() error { + st := status.New(codes.Unknown, c.Error()) + st, _ = st.WithDetails(&ss_common.ErrorInfo{ + Code: int32(c.Code()), + Msg: c.Error(), + }) + return st.Err() +} diff --git a/Server/common/net/http/http_resp/response.go b/Server/common/net/http/http_resp/response.go new file mode 100644 index 0000000..2a1730e --- /dev/null +++ b/Server/common/net/http/http_resp/response.go @@ -0,0 +1,22 @@ +package http_resp + +type RespJsonData struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data interface{} `json:"data,omitempty"` +} + +func Success(data interface{}) *RespJsonData { + return &RespJsonData{ + Code: OK.Code(), + Msg: OK.Error(), + Data: data, + } +} + +func Error(code int, message string) *RespJsonData { + return &RespJsonData{ + Code: code, + Msg: message, + } +} diff --git a/Server/common/proto/ss/grpc_pb/service_user.pb.go b/Server/common/proto/ss/grpc_pb/service_user.pb.go new file mode 100644 index 0000000..62e73d7 --- /dev/null +++ b/Server/common/proto/ss/grpc_pb/service_user.pb.go @@ -0,0 +1,224 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: service_user.proto + +package grpc_pb + +import ( + _ "common/proto/ss/ss_common" + _ "google.golang.org/genproto/googleapis/api/annotations" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type LoginReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Phone string `protobuf:"bytes,1,opt,name=Phone,json=phone,proto3" json:"Phone,omitempty"` // 手机号 + Code string `protobuf:"bytes,2,opt,name=Code,json=code,proto3" json:"Code,omitempty"` // 验证码 +} + +func (x *LoginReq) Reset() { + *x = LoginReq{} + if protoimpl.UnsafeEnabled { + mi := &file_service_user_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoginReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginReq) ProtoMessage() {} + +func (x *LoginReq) ProtoReflect() protoreflect.Message { + mi := &file_service_user_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoginReq.ProtoReflect.Descriptor instead. +func (*LoginReq) Descriptor() ([]byte, []int) { + return file_service_user_proto_rawDescGZIP(), []int{0} +} + +func (x *LoginReq) GetPhone() string { + if x != nil { + return x.Phone + } + return "" +} + +func (x *LoginReq) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +type LoginResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UID int32 `protobuf:"varint,1,opt,name=UID,json=uid,proto3" json:"UID,omitempty"` // 用户ID +} + +func (x *LoginResp) Reset() { + *x = LoginResp{} + if protoimpl.UnsafeEnabled { + mi := &file_service_user_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoginResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginResp) ProtoMessage() {} + +func (x *LoginResp) ProtoReflect() protoreflect.Message { + mi := &file_service_user_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoginResp.ProtoReflect.Descriptor instead. +func (*LoginResp) Descriptor() ([]byte, []int) { + return file_service_user_proto_rawDescGZIP(), []int{1} +} + +func (x *LoginResp) GetUID() int32 { + if x != nil { + return x.UID + } + return 0 +} + +var File_service_user_proto protoreflect.FileDescriptor + +var file_service_user_proto_rawDesc = []byte{ + 0x0a, 0x12, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0x34, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x12, + 0x14, 0x0a, 0x05, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x1d, 0x0a, 0x09, 0x4c, 0x6f, 0x67, + 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x49, 0x44, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x03, 0x75, 0x69, 0x64, 0x32, 0x3e, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, + 0x12, 0x36, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x09, 0x2e, 0x4c, 0x6f, 0x67, 0x69, + 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x0a, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x75, 0x73, + 0x65, 0x72, 0x2f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x42, 0x19, 0x5a, 0x17, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, + 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_service_user_proto_rawDescOnce sync.Once + file_service_user_proto_rawDescData = file_service_user_proto_rawDesc +) + +func file_service_user_proto_rawDescGZIP() []byte { + file_service_user_proto_rawDescOnce.Do(func() { + file_service_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_user_proto_rawDescData) + }) + return file_service_user_proto_rawDescData +} + +var file_service_user_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_service_user_proto_goTypes = []interface{}{ + (*LoginReq)(nil), // 0: LoginReq + (*LoginResp)(nil), // 1: LoginResp +} +var file_service_user_proto_depIdxs = []int32{ + 0, // 0: User.Login:input_type -> LoginReq + 1, // 1: User.Login:output_type -> LoginResp + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_service_user_proto_init() } +func file_service_user_proto_init() { + if File_service_user_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_service_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_service_user_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_service_user_proto_goTypes, + DependencyIndexes: file_service_user_proto_depIdxs, + MessageInfos: file_service_user_proto_msgTypes, + }.Build() + File_service_user_proto = out.File + file_service_user_proto_rawDesc = nil + file_service_user_proto_goTypes = nil + file_service_user_proto_depIdxs = nil +} diff --git a/Server/common/proto/ss/grpc_pb/service_user.pb.gw.go b/Server/common/proto/ss/grpc_pb/service_user.pb.gw.go new file mode 100644 index 0000000..7e0c4b7 --- /dev/null +++ b/Server/common/proto/ss/grpc_pb/service_user.pb.gw.go @@ -0,0 +1,154 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: service_user.proto + +/* +Package grpc_pb is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package grpc_pb + +import ( + "context" + "errors" + "io" + "net/http" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +// Suppress "imported and not used" errors +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) + +func request_User_Login_0(ctx context.Context, marshaler runtime.Marshaler, client UserClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq LoginReq + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.Login(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_User_Login_0(ctx context.Context, marshaler runtime.Marshaler, server UserServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq LoginReq + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.Login(ctx, &protoReq) + return msg, metadata, err +} + +// RegisterUserHandlerServer registers the http handlers for service User to "mux". +// UnaryRPC :call UserServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterUserHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. +func RegisterUserHandlerServer(ctx context.Context, mux *runtime.ServeMux, server UserServer) error { + mux.Handle(http.MethodPost, pattern_User_Login_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/.User/Login", runtime.WithHTTPPathPattern("/user/login")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_User_Login_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_User_Login_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + + return nil +} + +// RegisterUserHandlerFromEndpoint is same as RegisterUserHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterUserHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.NewClient(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + return RegisterUserHandler(ctx, mux, conn) +} + +// RegisterUserHandler registers the http handlers for service User to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterUserHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterUserHandlerClient(ctx, mux, NewUserClient(conn)) +} + +// RegisterUserHandlerClient registers the http handlers for service User +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "UserClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "UserClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "UserClient" to call the correct interceptors. This client ignores the HTTP middlewares. +func RegisterUserHandlerClient(ctx context.Context, mux *runtime.ServeMux, client UserClient) error { + mux.Handle(http.MethodPost, pattern_User_Login_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/.User/Login", runtime.WithHTTPPathPattern("/user/login")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_User_Login_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_User_Login_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + return nil +} + +var ( + pattern_User_Login_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"user", "login"}, "")) +) + +var ( + forward_User_Login_0 = runtime.ForwardResponseMessage +) diff --git a/Server/common/proto/ss/grpc_pb/service_user_grpc.pb.go b/Server/common/proto/ss/grpc_pb/service_user_grpc.pb.go new file mode 100644 index 0000000..d2c2e73 --- /dev/null +++ b/Server/common/proto/ss/grpc_pb/service_user_grpc.pb.go @@ -0,0 +1,105 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v4.25.1 +// source: service_user.proto + +package grpc_pb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// UserClient is the client API for User service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type UserClient interface { + Login(ctx context.Context, in *LoginReq, opts ...grpc.CallOption) (*LoginResp, error) +} + +type userClient struct { + cc grpc.ClientConnInterface +} + +func NewUserClient(cc grpc.ClientConnInterface) UserClient { + return &userClient{cc} +} + +func (c *userClient) Login(ctx context.Context, in *LoginReq, opts ...grpc.CallOption) (*LoginResp, error) { + out := new(LoginResp) + err := c.cc.Invoke(ctx, "/User/Login", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// UserServer is the server API for User service. +// All implementations must embed UnimplementedUserServer +// for forward compatibility +type UserServer interface { + Login(context.Context, *LoginReq) (*LoginResp, error) + mustEmbedUnimplementedUserServer() +} + +// UnimplementedUserServer must be embedded to have forward compatible implementations. +type UnimplementedUserServer struct { +} + +func (UnimplementedUserServer) Login(context.Context, *LoginReq) (*LoginResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method Login not implemented") +} +func (UnimplementedUserServer) mustEmbedUnimplementedUserServer() {} + +// UnsafeUserServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to UserServer will +// result in compilation errors. +type UnsafeUserServer interface { + mustEmbedUnimplementedUserServer() +} + +func RegisterUserServer(s grpc.ServiceRegistrar, srv UserServer) { + s.RegisterService(&User_ServiceDesc, srv) +} + +func _User_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LoginReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServer).Login(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/User/Login", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServer).Login(ctx, req.(*LoginReq)) + } + return interceptor(ctx, in, info, handler) +} + +// User_ServiceDesc is the grpc.ServiceDesc for User service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var User_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "User", + HandlerType: (*UserServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Login", + Handler: _User_Login_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "service_user.proto", +} diff --git a/Server/common/proto/ss/ss_common/ss_common.pb.go b/Server/common/proto/ss/ss_common/ss_common.pb.go index d070b7b..39424c0 100644 --- a/Server/common/proto/ss/ss_common/ss_common.pb.go +++ b/Server/common/proto/ss/ss_common/ss_common.pb.go @@ -10,6 +10,7 @@ import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" + sync "sync" ) const ( @@ -19,16 +20,89 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type ErrorInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Msg string `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"` +} + +func (x *ErrorInfo) Reset() { + *x = ErrorInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_ss_common_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ErrorInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ErrorInfo) ProtoMessage() {} + +func (x *ErrorInfo) ProtoReflect() protoreflect.Message { + mi := &file_ss_common_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ErrorInfo.ProtoReflect.Descriptor instead. +func (*ErrorInfo) Descriptor() ([]byte, []int) { + return file_ss_common_proto_rawDescGZIP(), []int{0} +} + +func (x *ErrorInfo) GetCode() int32 { + if x != nil { + return x.Code + } + return 0 +} + +func (x *ErrorInfo) GetMsg() string { + if x != nil { + return x.Msg + } + return "" +} + var File_ss_common_proto protoreflect.FileDescriptor var file_ss_common_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x42, 0x1b, 0x5a, 0x19, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x73, 0x73, 0x2f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x22, 0x31, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, + 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, + 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6d, 0x73, 0x67, 0x42, 0x1b, 0x5a, 0x19, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x73, 0x2f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } -var file_ss_common_proto_goTypes = []interface{}{} +var ( + file_ss_common_proto_rawDescOnce sync.Once + file_ss_common_proto_rawDescData = file_ss_common_proto_rawDesc +) + +func file_ss_common_proto_rawDescGZIP() []byte { + file_ss_common_proto_rawDescOnce.Do(func() { + file_ss_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_ss_common_proto_rawDescData) + }) + return file_ss_common_proto_rawDescData +} + +var file_ss_common_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_ss_common_proto_goTypes = []interface{}{ + (*ErrorInfo)(nil), // 0: ErrorInfo +} var file_ss_common_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type @@ -42,18 +116,33 @@ func file_ss_common_proto_init() { if File_ss_common_proto != nil { return } + if !protoimpl.UnsafeEnabled { + file_ss_common_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ErrorInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_ss_common_proto_rawDesc, NumEnums: 0, - NumMessages: 0, + NumMessages: 1, NumExtensions: 0, NumServices: 0, }, GoTypes: file_ss_common_proto_goTypes, DependencyIndexes: file_ss_common_proto_depIdxs, + MessageInfos: file_ss_common_proto_msgTypes, }.Build() File_ss_common_proto = out.File file_ss_common_proto_rawDesc = nil diff --git a/Server/gateway/app/app.go b/Server/gateway/app/app.go index 5b04f71..6936053 100644 --- a/Server/gateway/app/app.go +++ b/Server/gateway/app/app.go @@ -22,7 +22,7 @@ func (p *Program) Init(_ svc.Environment) error { p.moduleList = append(p.moduleList, &ModuleBase{}) p.moduleList = append(p.moduleList, &ModuleDB{}) p.moduleList = append(p.moduleList, &ModulePrometheus{}) - p.moduleList = append(p.moduleList, &ModuleWebServer{}) + p.moduleList = append(p.moduleList, &ModuleGrpcGateway{}) p.moduleList = append(p.moduleList, &ModuleWebsocketServer{}) p.moduleList = append(p.moduleList, &ModuleGrpcServer{}) diff --git a/Server/gateway/app/grpc.go b/Server/gateway/app/grpc.go index 03c947b..2a08f80 100644 --- a/Server/gateway/app/grpc.go +++ b/Server/gateway/app/grpc.go @@ -3,7 +3,7 @@ package app import ( "common/net/grpc/service" "gateway/config" - "gateway/grpc_server/server" + "gateway/internal/grpc_server/server" ) // ModuleGrpcServer Grpc服务模块 diff --git a/Server/gateway/app/grpc_gateway.go b/Server/gateway/app/grpc_gateway.go new file mode 100644 index 0000000..237538a --- /dev/null +++ b/Server/gateway/app/grpc_gateway.go @@ -0,0 +1,63 @@ +package app + +import ( + "common/log" + "common/net/grpc/service" + "common/proto/ss/grpc_pb" + "context" + "errors" + "fmt" + "gateway/config" + "gateway/internal/net/http_gateway" + "net/http" + "sync" +) + +// ModuleGrpcGateway GrpcGateway服务模块 +type ModuleGrpcGateway struct { + wg *sync.WaitGroup + // 微服务列表 + services []service.IService + server *http.Server +} + +func (m *ModuleGrpcGateway) init() error { + m.wg = &sync.WaitGroup{} + return nil +} + +func (m *ModuleGrpcGateway) start() error { + m.wg.Add(1) + go func() { + defer m.wg.Done() + conn, err := service.UserNewClientLB() + if err != nil { + log.Errorf("get user conn failed: %v", err) + return + } + + gwMux := http_gateway.InitServeMux() + if err = grpc_pb.RegisterUserHandlerClient(context.Background(), gwMux, conn); err != nil { + log.Errorf("RegisterUserHandlerClient err: %v", err) + return + } + + m.server = &http.Server{ + Addr: fmt.Sprintf("%v:%v", config.Get().Serve.Http.Address, config.Get().Serve.Http.Port), + Handler: http_gateway.InitRouter(gwMux), + } + if err := m.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { + log.Errorf("http server failed: %v", err.Error()) + } + log.Infof("http server stop.") + }() + return nil +} + +func (m *ModuleGrpcGateway) stop() error { + if err := m.server.Shutdown(context.Background()); err != nil { + log.Errorf("stop http server failed: %v", err) + } + m.wg.Wait() + return nil +} diff --git a/Server/gateway/app/web.go b/Server/gateway/app/web.go deleted file mode 100644 index f9376d6..0000000 --- a/Server/gateway/app/web.go +++ /dev/null @@ -1,50 +0,0 @@ -package app - -import ( - "common/log" - "context" - "errors" - "fmt" - "gateway/config" - "gateway/net/http_gateway" - "github.com/gin-gonic/gin" - "net/http" - "sync" -) - -// ModuleWebServer Web服务模块 -type ModuleWebServer struct { - wg *sync.WaitGroup - server *http.Server - router *gin.Engine -} - -func (m *ModuleWebServer) init() error { - m.wg = &sync.WaitGroup{} - m.router = http_gateway.InitRouter() - return nil -} - -func (m *ModuleWebServer) start() error { - m.wg.Add(1) - go func() { - defer m.wg.Done() - m.server = &http.Server{ - Addr: fmt.Sprintf("%v:%v", config.Get().Serve.Http.Address, config.Get().Serve.Http.Port), - Handler: m.router, - } - if err := m.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { - log.Errorf("http server failed: %v", err.Error()) - } - log.Infof("http server stop.") - }() - return nil -} - -func (m *ModuleWebServer) stop() error { - if err := m.server.Shutdown(context.Background()); err != nil { - log.Errorf("stop http server failed: %v", err) - } - m.wg.Wait() - return nil -} diff --git a/Server/gateway/app/websocket.go b/Server/gateway/app/websocket.go index 81a1a1d..c986bf3 100644 --- a/Server/gateway/app/websocket.go +++ b/Server/gateway/app/websocket.go @@ -5,7 +5,7 @@ import ( "common/net/socket/websocket" "fmt" "gateway/config" - "gateway/net/ws_gateway" + "gateway/internal/net/ws_gateway" "sync" "time" ) diff --git a/Server/gateway/config/config.dev.yaml b/Server/gateway/config/config.dev.yaml index 7b029ab..5a3b286 100644 --- a/Server/gateway/config/config.dev.yaml +++ b/Server/gateway/config/config.dev.yaml @@ -16,14 +16,6 @@ monitor: db: etcd: endpoints: [ "10.0.40.9:2379" ] - mysql: - user: - dsn: "root:gR9pV4tY7zR6qL3e@tcp(47.108.184.184:3306)/point?charset=utf8mb4&parseTime=True&loc=Local" - max_open_conn: 50 - max_idle_conn: 20 - conn_max_lifetime_sec: 600 - conn_max_idle_time_sec: 180 - log_level: "warn" serve: grpc: diff --git a/Server/gateway/config/config.prod.yaml b/Server/gateway/config/config.prod.yaml index 89f4ad7..bab9ee0 100644 --- a/Server/gateway/config/config.prod.yaml +++ b/Server/gateway/config/config.prod.yaml @@ -16,14 +16,6 @@ monitor: db: etcd: endpoints: [ "172.18.28.0:2379" ] - mysql: - user: - dsn: "root:gR9pV4tY7zR6qL3e@tcp(47.108.184.184:3306)/point?charset=utf8mb4&parseTime=True&loc=Local" - max_open_conn: 50 - max_idle_conn: 20 - conn_max_lifetime_sec: 600 - conn_max_idle_time_sec: 180 - log_level: "warn" serve: grpc: diff --git a/Server/gateway/go.mod b/Server/gateway/go.mod index 6e80c05..f57bdf5 100644 --- a/Server/gateway/go.mod +++ b/Server/gateway/go.mod @@ -6,6 +6,7 @@ require ( common v0.0.0-00010101000000-000000000000 github.com/gin-contrib/cors v1.7.6 github.com/gin-gonic/gin v1.10.1 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 github.com/judwhite/go-svc v1.2.1 github.com/prometheus/client_golang v1.20.5 go.uber.org/zap v1.27.0 @@ -38,7 +39,6 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect diff --git a/Server/gateway/handler/http_handler/helper/base.go b/Server/gateway/handler/http_handler/helper/base.go deleted file mode 100644 index 5b02db8..0000000 --- a/Server/gateway/handler/http_handler/helper/base.go +++ /dev/null @@ -1,18 +0,0 @@ -package helper - -type Pagination struct { - Page int `json:"page"` // 页 - Size int `json:"size"` // 页大小 -} - -//func SetBaseQuery(page *Pagination, order string) func(db *gorm.DB) *gorm.DB { -// return func(db *gorm.DB) *gorm.DB { -// if page != nil { -// db = db.Offset((page.Page - 1) * page.Size).Limit(page.Size) -// } -// if len(order) > 0 { -// db = db.Order(order) -// } -// return db -// } -//} diff --git a/Server/gateway/handler/http_handler/helper/render/code.go b/Server/gateway/handler/http_handler/helper/render/code.go deleted file mode 100644 index db47dc5..0000000 --- a/Server/gateway/handler/http_handler/helper/render/code.go +++ /dev/null @@ -1,31 +0,0 @@ -package render - -var ( - OK = NewCode(0, "成功") - Failed = NewCode(1, "失败") - ParamError = NewCode(1001, "参数错误") - NameEmpty = NewCode(1002, "名称不能为空") - NameDuplicate = NewCode(1003, "名称或编号不能重复") - ListEmpty = NewCode(1004, "列表不能为空") - RepeatCommit = NewCode(1005, "请勿重复提交") -) - -type Code struct { - code int - message string -} - -func NewCode(code int, message string) *Code { - return &Code{ - code: code, - message: message, - } -} - -func (c *Code) Code() int { - return c.code -} - -func (c *Code) Message() string { - return c.message -} diff --git a/Server/gateway/handler/http_handler/helper/render/render.go b/Server/gateway/handler/http_handler/helper/render/render.go deleted file mode 100644 index 2349f2b..0000000 --- a/Server/gateway/handler/http_handler/helper/render/render.go +++ /dev/null @@ -1,39 +0,0 @@ -package render - -import ( - "github.com/gin-gonic/gin" - "net/http" -) - -type RespJsonData struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data interface{} `json:"data"` -} - -func Json(c *gin.Context, code *Code, data interface{}) { - result := &RespJsonData{ - Code: code.Code(), - Msg: code.Message(), - Data: data, - } - c.JSON(http.StatusOK, result) -} - -func JsonByStatus(c *gin.Context, status int, code *Code, data interface{}) { - result := &RespJsonData{ - Code: code.Code(), - Msg: code.Message(), - Data: data, - } - c.JSON(status, result) -} - -func AbortJson(c *gin.Context, code *Code, data interface{}) { - result := &RespJsonData{ - Code: code.Code(), - Msg: code.Message(), - Data: data, - } - c.AbortWithStatusJSON(http.StatusOK, result) -} diff --git a/Server/gateway/handler/http_handler/unique_id.go b/Server/gateway/handler/http_handler/unique_id.go deleted file mode 100644 index 175b0e5..0000000 --- a/Server/gateway/handler/http_handler/unique_id.go +++ /dev/null @@ -1,16 +0,0 @@ -package http_handler - -import ( - "common/utils" - "gateway/handler/http_handler/helper/render" - "github.com/gin-gonic/gin" -) - -type UniqueIDResp struct { - ID string `json:"id"` -} - -// GenSnowflake 生成雪花ID -func GenSnowflake(c *gin.Context) { - render.Json(c, render.OK, &UniqueIDResp{ID: utils.SnowflakeInstance().Generate().String()}) -} diff --git a/Server/gateway/grpc_server/server/server.go b/Server/gateway/internal/grpc_server/server/server.go similarity index 97% rename from Server/gateway/grpc_server/server/server.go rename to Server/gateway/internal/grpc_server/server/server.go index 797b2f1..191b44e 100644 --- a/Server/gateway/grpc_server/server/server.go +++ b/Server/gateway/internal/grpc_server/server/server.go @@ -4,7 +4,7 @@ import ( "common/log" "common/proto/sc/sc_pb" "common/proto/ss/grpc_pb" - "gateway/handler/ws_handler" + "gateway/internal/handler/ws_handler" "google.golang.org/protobuf/proto" "sync" ) diff --git a/Server/gateway/grpc_server/server/server_init.go b/Server/gateway/internal/grpc_server/server/server_init.go similarity index 93% rename from Server/gateway/grpc_server/server/server_init.go rename to Server/gateway/internal/grpc_server/server/server_init.go index a3df142..c677208 100644 --- a/Server/gateway/grpc_server/server/server_init.go +++ b/Server/gateway/internal/grpc_server/server/server_init.go @@ -4,7 +4,7 @@ import ( "common/discover/common" "common/net/grpc/service" "common/proto/ss/grpc_pb" - "gateway/handler/ws_handler" + "gateway/internal/handler/ws_handler" "google.golang.org/grpc" ) diff --git a/Server/gateway/grpc_server/stream_client/scene.go b/Server/gateway/internal/grpc_server/stream_client/scene.go similarity index 100% rename from Server/gateway/grpc_server/stream_client/scene.go rename to Server/gateway/internal/grpc_server/stream_client/scene.go diff --git a/Server/gateway/handler/ws_handler/client.go b/Server/gateway/internal/handler/ws_handler/client.go similarity index 100% rename from Server/gateway/handler/ws_handler/client.go rename to Server/gateway/internal/handler/ws_handler/client.go diff --git a/Server/gateway/handler/ws_handler/client_write.go b/Server/gateway/internal/handler/ws_handler/client_write.go similarity index 100% rename from Server/gateway/handler/ws_handler/client_write.go rename to Server/gateway/internal/handler/ws_handler/client_write.go diff --git a/Server/gateway/handler/ws_handler/event.go b/Server/gateway/internal/handler/ws_handler/event.go similarity index 100% rename from Server/gateway/handler/ws_handler/event.go rename to Server/gateway/internal/handler/ws_handler/event.go diff --git a/Server/gateway/handler/ws_handler/handler.go b/Server/gateway/internal/handler/ws_handler/handler.go similarity index 96% rename from Server/gateway/handler/ws_handler/handler.go rename to Server/gateway/internal/handler/ws_handler/handler.go index 4b5087c..d9610a9 100644 --- a/Server/gateway/handler/ws_handler/handler.go +++ b/Server/gateway/internal/handler/ws_handler/handler.go @@ -4,7 +4,7 @@ import ( "common/net/grpc/service" "common/proto/sc/sc_pb" "common/proto/ss/grpc_pb" - "gateway/grpc_server/stream_client" + "gateway/internal/grpc_server/stream_client" "google.golang.org/protobuf/proto" "time" ) @@ -42,7 +42,7 @@ func (c *Client) handle(event Event) { } func (c *Client) onEnter(msg *sc_pb.C2S_EnterInstance) { - client, err := service.SceneNewClient() + client, err := service.SceneNewClientLB() if err != nil { c.logger.Errorf("SceneNewClient err: %v", err) return diff --git a/Server/gateway/handler/ws_handler/manager.go b/Server/gateway/internal/handler/ws_handler/manager.go similarity index 100% rename from Server/gateway/handler/ws_handler/manager.go rename to Server/gateway/internal/handler/ws_handler/manager.go diff --git a/Server/gateway/net/http_gateway/middleward.go b/Server/gateway/internal/net/http_gateway/middleward.go similarity index 100% rename from Server/gateway/net/http_gateway/middleward.go rename to Server/gateway/internal/net/http_gateway/middleward.go diff --git a/Server/gateway/internal/net/http_gateway/router.go b/Server/gateway/internal/net/http_gateway/router.go new file mode 100644 index 0000000..d4fced2 --- /dev/null +++ b/Server/gateway/internal/net/http_gateway/router.go @@ -0,0 +1,54 @@ +package http_gateway + +import ( + "common/log" + "common/net/http/http_resp" + wrapper2 "gateway/internal/net/http_gateway/wrapper" + "github.com/gin-contrib/cors" + "github.com/gin-gonic/gin" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "google.golang.org/protobuf/encoding/protojson" + "net/http" +) + +func InitServeMux() *runtime.ServeMux { + baseMarshaler := &runtime.JSONPb{ + MarshalOptions: protojson.MarshalOptions{ + UseProtoNames: false, + EmitUnpopulated: true, + }, + UnmarshalOptions: protojson.UnmarshalOptions{ + DiscardUnknown: true, + }, + } + unifiedMarshaler := wrapper2.NewWrappedMarshaler(baseMarshaler) + + mux := runtime.NewServeMux( + runtime.WithMarshalerOption(runtime.MIMEWildcard, unifiedMarshaler), + runtime.WithErrorHandler(wrapper2.ErrorHandler), + ) + return mux +} + +func InitRouter(mux *runtime.ServeMux) *gin.Engine { + gin.SetMode(gin.ReleaseMode) + + r := gin.New() + r.Use( + gin.Recovery(), + ginLogger(log.GetLogger().Named("GIN")), + cors.New(corsConfig()), + ) + + r.HandleMethodNotAllowed = true + r.NoMethod(func(c *gin.Context) { + c.JSON(http.StatusMethodNotAllowed, http_resp.Error(http_resp.Failed.Code(), "Method Not Allowed")) + }) + r.NoRoute(func(c *gin.Context) { + c.JSON(http.StatusNotFound, http_resp.Error(http_resp.Failed.Code(), "Endpoint Not Found")) + }) + + r.Any("/*any", gin.WrapH(mux)) + + return r +} diff --git a/Server/gateway/internal/net/http_gateway/wrapper/error_handler.go b/Server/gateway/internal/net/http_gateway/wrapper/error_handler.go new file mode 100644 index 0000000..f9afb46 --- /dev/null +++ b/Server/gateway/internal/net/http_gateway/wrapper/error_handler.go @@ -0,0 +1,53 @@ +package wrapper + +import ( + "common/net/http/http_resp" + "common/proto/ss/ss_common" + "context" + "encoding/json" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "net/http" +) + +// ErrorHandler 将 gRPC 错误转为统一 JSON 格式 +func ErrorHandler(_ context.Context, _ *runtime.ServeMux, _ runtime.Marshaler, w http.ResponseWriter, _ *http.Request, err error) { + st, ok := status.FromError(err) + if !ok { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusInternalServerError) + _ = json.NewEncoder(w).Encode(http_resp.Error(http_resp.Failed.Code(), http_resp.Failed.Error())) + return + } + + code, msg := 0, "" + for _, detail := range st.Details() { + if errorInfo, ok := detail.(*ss_common.ErrorInfo); ok { + code = int(errorInfo.Code) + msg = errorInfo.Msg + break + } + } + if code == 0 { + code = http_resp.Failed.Code() + msg = http_resp.Failed.Error() + } + if st.Code() == codes.Unknown { + msg = st.Message() + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(grpcCodeToHTTPCode(st.Code())) + _ = json.NewEncoder(w).Encode(http_resp.Error(code, msg)) +} + +// 这里定义 Internal 属于业务错误,其他的属于 500 报错 +func grpcCodeToHTTPCode(c codes.Code) int { + switch c { + case codes.OK, codes.Unknown: + return http.StatusOK + default: + return http.StatusInternalServerError + } +} diff --git a/Server/gateway/internal/net/http_gateway/wrapper/marshal.go b/Server/gateway/internal/net/http_gateway/wrapper/marshal.go new file mode 100644 index 0000000..9fa5612 --- /dev/null +++ b/Server/gateway/internal/net/http_gateway/wrapper/marshal.go @@ -0,0 +1,42 @@ +package wrapper + +import ( + "common/net/http/http_resp" + "encoding/json" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "io" +) + +// WrappedMarshaler 自动包装响应为 { code, message, data } +type WrappedMarshaler struct { + inner runtime.Marshaler +} + +func NewWrappedMarshaler(inner runtime.Marshaler) *WrappedMarshaler { + return &WrappedMarshaler{inner: inner} +} + +// Marshal 将 gRPC 响应包装成统一格式 +func (w *WrappedMarshaler) Marshal(v interface{}) ([]byte, error) { + dataBytes, err := w.inner.Marshal(v) + if err != nil { + return json.Marshal(http_resp.Error(http_resp.Failed.Code(), http_resp.Failed.Error())) + } + return json.Marshal(http_resp.Success(json.RawMessage(dataBytes))) +} + +func (w *WrappedMarshaler) Unmarshal(data []byte, v interface{}) error { + return w.inner.Unmarshal(data, v) +} + +func (w *WrappedMarshaler) NewDecoder(r io.Reader) runtime.Decoder { + return w.inner.NewDecoder(r) +} + +func (w *WrappedMarshaler) NewEncoder(wr io.Writer) runtime.Encoder { + return w.inner.NewEncoder(wr) +} + +func (w *WrappedMarshaler) ContentType(v interface{}) string { + return "application/json" +} diff --git a/Server/gateway/net/ws_gateway/server.go b/Server/gateway/internal/net/ws_gateway/server.go similarity index 73% rename from Server/gateway/net/ws_gateway/server.go rename to Server/gateway/internal/net/ws_gateway/server.go index f44dbb6..be63a20 100644 --- a/Server/gateway/net/ws_gateway/server.go +++ b/Server/gateway/internal/net/ws_gateway/server.go @@ -4,7 +4,7 @@ import ( "common/log" "common/net/socket" "fmt" - "gateway/handler/ws_handler" + ws_handler2 "gateway/internal/handler/ws_handler" "go.uber.org/zap" "strconv" "time" @@ -30,29 +30,29 @@ func (g *GatewayWsServer) OnHandShake(conn socket.ISocketConn) { if err != nil { _ = conn.Close() } - if oldClient := ws_handler.UserMgr.GetByUID(int32(t)); oldClient != nil { + if oldClient := ws_handler2.UserMgr.GetByUID(int32(t)); oldClient != nil { oldClient.CloseClient() } - client := ws_handler.NewClient(int32(t), conn) - ws_handler.UserMgr.Add(int32(t), client) + client := ws_handler2.NewClient(int32(t), conn) + ws_handler2.UserMgr.Add(int32(t), client) conn.SetParam("client", client) } func (g *GatewayWsServer) OnMessage(conn socket.ISocketConn, bytes []byte) socket.Action { - client, ok := conn.GetParam("client").(*ws_handler.Client) + client, ok := conn.GetParam("client").(*ws_handler2.Client) if !ok || client.UID == 0 { return socket.Close } - client.OnEvent(&ws_handler.ClientEvent{Msg: bytes}) + client.OnEvent(&ws_handler2.ClientEvent{Msg: bytes}) return socket.None } func (g *GatewayWsServer) OnPong(conn socket.ISocketConn) { - client, ok := conn.GetParam("client").(*ws_handler.Client) + client, ok := conn.GetParam("client").(*ws_handler2.Client) if !ok || client.UID == 0 { return } - client.OnEvent(&ws_handler.PongEvent{}) + client.OnEvent(&ws_handler2.PongEvent{}) } func (g *GatewayWsServer) OnClose(_ socket.ISocketConn, _ error) socket.Action { diff --git a/Server/gateway/net/http_gateway/router.go b/Server/gateway/net/http_gateway/router.go deleted file mode 100644 index 0601188..0000000 --- a/Server/gateway/net/http_gateway/router.go +++ /dev/null @@ -1,37 +0,0 @@ -package http_gateway - -import ( - "common/log" - "gateway/handler/http_handler" - "gateway/handler/http_handler/helper/render" - "github.com/gin-contrib/cors" - "github.com/gin-gonic/gin" - "net/http" -) - -func InitRouter() *gin.Engine { - gin.SetMode(gin.ReleaseMode) - - r := gin.New() - r.Use( - gin.Recovery(), - ginLogger(log.GetLogger().Named("GIN")), - cors.New(corsConfig()), - ) - - r.HandleMethodNotAllowed = true - r.NoMethod(func(c *gin.Context) { - render.JsonByStatus(c, http.StatusMethodNotAllowed, render.Failed, "Method Not Allowed") - }) - r.NoRoute(func(c *gin.Context) { - render.JsonByStatus(c, http.StatusNotFound, render.Failed, "Endpoint Not Found") - }) - initBaseRouter(r) - - return r -} - -func initBaseRouter(router *gin.Engine) { - g := router.Group("/b") - g.POST("/snowflake", http_handler.GenSnowflake) // 生成雪花 -} diff --git a/Server/robot/app/websocket.go b/Server/robot/app/websocket.go index 150302e..be96a5c 100644 --- a/Server/robot/app/websocket.go +++ b/Server/robot/app/websocket.go @@ -3,7 +3,7 @@ package app import ( "fmt" "robot/config" - "robot/ws" + "robot/internal/ws" ) // ModuleWebsocket Websocket客户端模块 diff --git a/Server/robot/ws/client.go b/Server/robot/internal/ws/client.go similarity index 100% rename from Server/robot/ws/client.go rename to Server/robot/internal/ws/client.go diff --git a/Server/robot/ws/handler.go b/Server/robot/internal/ws/handler.go similarity index 100% rename from Server/robot/ws/handler.go rename to Server/robot/internal/ws/handler.go diff --git a/Server/robot/ws/manager.go b/Server/robot/internal/ws/manager.go similarity index 100% rename from Server/robot/ws/manager.go rename to Server/robot/internal/ws/manager.go diff --git a/Server/robot/ws/router.go b/Server/robot/internal/ws/router.go similarity index 100% rename from Server/robot/ws/router.go rename to Server/robot/internal/ws/router.go diff --git a/Server/scene/app/grpc.go b/Server/scene/app/grpc.go index 8a34fb9..0438b5c 100644 --- a/Server/scene/app/grpc.go +++ b/Server/scene/app/grpc.go @@ -3,7 +3,7 @@ package app import ( "common/net/grpc/service" "scene/config" - "scene/grpc_server/server" + "scene/internal/grpc_server/server" ) // ModuleGrpcServer Grpc服务模块 diff --git a/Server/scene/grpc_server/server/server.go b/Server/scene/internal/grpc_server/server/server.go similarity index 80% rename from Server/scene/grpc_server/server/server.go rename to Server/scene/internal/grpc_server/server/server.go index 743d806..f8c5bc1 100644 --- a/Server/scene/grpc_server/server/server.go +++ b/Server/scene/internal/grpc_server/server/server.go @@ -6,17 +6,17 @@ import ( "common/proto/ss/grpc_pb" "context" "google.golang.org/protobuf/proto" - "scene/instance" + instance2 "scene/internal/instance" "sync" ) func (s *Server) Enter(ctx context.Context, req *grpc_pb.EnterReq) (*grpc_pb.EnterResp, error) { - var i *instance.Instance - if len(instance.Mgr.GetAll()) == 0 { - i = instance.NewScene(s.SID, req.InstanceID) + var i *instance2.Instance + if len(instance2.Mgr.GetAll()) == 0 { + i = instance2.NewScene(s.SID, req.InstanceID) i.Start(s.EtcdTTL) } else { - for _, v := range instance.Mgr.GetAll() { + for _, v := range instance2.Mgr.GetAll() { i = v break } @@ -39,7 +39,7 @@ func (s *Server) Enter(ctx context.Context, req *grpc_pb.EnterReq) (*grpc_pb.Ent } func (s *Server) Leave(ctx context.Context, req *grpc_pb.LeaveReq) (*grpc_pb.LeaveResp, error) { - if i := instance.Mgr.GetByUniqueNo(req.UniqueNo); i != nil { + if i := instance2.Mgr.GetByUniqueNo(req.UniqueNo); i != nil { i.EventIn <- req } return &grpc_pb.LeaveResp{}, nil @@ -59,7 +59,7 @@ func (s *Server) Action(server grpc_pb.Scene_ActionServer) error { if args, err := server.Recv(); err != nil { return } else { - if ins := instance.Mgr.GetByUniqueNo(args.UniqueNo); ins != nil { + if ins := instance2.Mgr.GetByUniqueNo(args.UniqueNo); ins != nil { select { case ins.EventIn <- args: default: diff --git a/Server/scene/grpc_server/server/server_init.go b/Server/scene/internal/grpc_server/server/server_init.go similarity index 100% rename from Server/scene/grpc_server/server/server_init.go rename to Server/scene/internal/grpc_server/server/server_init.go diff --git a/Server/scene/grpc_server/stream_client/gateway.go b/Server/scene/internal/grpc_server/stream_client/gateway.go similarity index 100% rename from Server/scene/grpc_server/stream_client/gateway.go rename to Server/scene/internal/grpc_server/stream_client/gateway.go diff --git a/Server/scene/instance/instance.go b/Server/scene/internal/instance/instance.go similarity index 98% rename from Server/scene/instance/instance.go rename to Server/scene/internal/instance/instance.go index 30542b5..319a23d 100644 --- a/Server/scene/instance/instance.go +++ b/Server/scene/internal/instance/instance.go @@ -11,8 +11,8 @@ import ( "go.uber.org/zap" "google.golang.org/protobuf/proto" "runtime/debug" - "scene/grpc_server/stream_client" - "scene/npc" + "scene/internal/grpc_server/stream_client" + "scene/internal/npc" "sync" "time" ) diff --git a/Server/scene/instance/manager.go b/Server/scene/internal/instance/manager.go similarity index 100% rename from Server/scene/instance/manager.go rename to Server/scene/internal/instance/manager.go diff --git a/Server/scene/npc/npc.go b/Server/scene/internal/npc/npc.go similarity index 100% rename from Server/scene/npc/npc.go rename to Server/scene/internal/npc/npc.go diff --git a/Server/scene/npc/player.go b/Server/scene/internal/npc/player.go similarity index 100% rename from Server/scene/npc/player.go rename to Server/scene/internal/npc/player.go diff --git a/Server/user/Dockerfile b/Server/user/Dockerfile new file mode 100644 index 0000000..5a61884 --- /dev/null +++ b/Server/user/Dockerfile @@ -0,0 +1,11 @@ +FROM alpine:latest + +RUN apk add --no-cache tzdata && \ + ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ + echo "Asia/Shanghai" > /etc/timezone + +COPY user/ /app/ +RUN chmod 777 /app/server-user + +WORKDIR /app +CMD ["./server-user"] \ No newline at end of file diff --git a/Server/user/app/app.go b/Server/user/app/app.go new file mode 100644 index 0000000..8b99abf --- /dev/null +++ b/Server/user/app/app.go @@ -0,0 +1,58 @@ +package app + +import ( + "common/discover" + "common/log" + "fmt" + "github.com/judwhite/go-svc" + "user/config" +) + +type Program struct { + moduleList []Module // 模块列表 +} + +type Module interface { + init() error + start() error + stop() error +} + +func (p *Program) Init(_ svc.Environment) error { + p.moduleList = append(p.moduleList, &ModuleBase{}) + p.moduleList = append(p.moduleList, &ModuleDB{}) + p.moduleList = append(p.moduleList, &ModuleGrpcServer{}) + + for _, module := range p.moduleList { + if err := module.init(); err != nil { + return err + } + } + log.Infof(fmt.Sprintf("%v Init successful...", config.Get().App.Name)) + return nil +} + +func (p *Program) Start() error { + for _, module := range p.moduleList { + if err := module.start(); err != nil { + return err + } + } + discover.Listen() + + log.Infof(fmt.Sprintf("%v Start successful...", config.Get().App.Name)) + return nil +} + +func (p *Program) Stop() error { + discover.Close() + for i := len(p.moduleList) - 1; i >= 0; i-- { + module := p.moduleList[i] + if err := module.stop(); err != nil { + log.Errorf("module stop error: %v", err) + } + } + + log.Infof(fmt.Sprintf("%v Stop successful...", config.Get().App.Name)) + return nil +} diff --git a/Server/user/app/base.go b/Server/user/app/base.go new file mode 100644 index 0000000..ffb7184 --- /dev/null +++ b/Server/user/app/base.go @@ -0,0 +1,33 @@ +package app + +import ( + "common/log" + "common/utils" + "math/rand" + "user/config" +) + +// ModuleBase 基础模块,或者一些零散的模块 +type ModuleBase struct { +} + +func (p *ModuleBase) init() error { + // 配置 + if err := config.LoadConfig(); err != nil { + return err + } + cfg := config.Get() + // 日志 + log.Init(cfg.Log.Debug, cfg.Log.MaxSize, cfg.Log.MaxBackups, cfg.Log.MaxAge, cfg.Log.Level) + // 雪花 + utils.InitSnowflake(int64(rand.Intn(1000))) + return nil +} + +func (p *ModuleBase) start() error { + return nil +} + +func (p *ModuleBase) stop() error { + return nil +} diff --git a/Server/user/app/db.go b/Server/user/app/db.go new file mode 100644 index 0000000..d387068 --- /dev/null +++ b/Server/user/app/db.go @@ -0,0 +1,23 @@ +package app + +import ( + "common/db" + "user/config" +) + +// ModuleDB 数据库模块 +type ModuleDB struct { + dbModule *db.ModuleDB +} + +func (p *ModuleDB) init() error { + return p.dbModule.Init(config.Get().DB) +} + +func (p *ModuleDB) start() error { + return nil +} + +func (p *ModuleDB) stop() error { + return p.dbModule.Stop() +} diff --git a/Server/user/app/grpc.go b/Server/user/app/grpc.go new file mode 100644 index 0000000..a544d76 --- /dev/null +++ b/Server/user/app/grpc.go @@ -0,0 +1,27 @@ +package app + +import ( + "common/net/grpc/service" + "user/config" + "user/internal/grpc_server/server" +) + +// ModuleGrpcServer Grpc服务模块 +type ModuleGrpcServer struct { + server service.IService +} + +func (m *ModuleGrpcServer) init() error { + return nil +} + +func (m *ModuleGrpcServer) start() error { + m.server = server.NewServer(config.Get().Serve.Grpc.TTL) + m.server.Init(config.Get().Serve.Grpc.Address, config.Get().Serve.Grpc.Port) + return nil +} + +func (m *ModuleGrpcServer) stop() error { + m.server.Close() + return nil +} diff --git a/Server/user/config/config.dev.yaml b/Server/user/config/config.dev.yaml new file mode 100644 index 0000000..aeb1938 --- /dev/null +++ b/Server/user/config/config.dev.yaml @@ -0,0 +1,27 @@ +app: + name: "user-dev" + +log: + debug: true + level: "debug" + maxSize: 10 + maxBackups: 100 + maxAge: 7 + +db: + etcd: + endpoints: [ "10.0.40.9:2379" ] + mysql: + user_db: + dsn: "root:gR9pV4tY7zR6qL3e@tcp(47.108.184.184:3306)/user_db?charset=utf8mb4&parseTime=True&loc=Local" + max_open_conn: 50 + max_idle_conn: 20 + conn_max_lifetime_sec: 600 + conn_max_idle_time_sec: 180 + log_level: "warn" + +serve: + grpc: + address: "127.0.0.1" + port: 8602 + ttl: 20 diff --git a/Server/user/config/config.go b/Server/user/config/config.go new file mode 100644 index 0000000..0abe5cd --- /dev/null +++ b/Server/user/config/config.go @@ -0,0 +1,25 @@ +package config + +import "common/config" + +const path = "./config" + +type Config struct { + App *config.AppConfig `yaml:"app"` + Log *config.LogConfig `yaml:"log"` + DB *config.DBConfig `yaml:"db"` + Serve *config.ServeConfig `yaml:"serve"` +} + +var cfg *Config + +// LoadConfig 加载应用配置 +func LoadConfig() error { + c, err := config.LoadConfig(path, cfg) + cfg = c + return err +} + +func Get() *Config { + return cfg +} diff --git a/Server/user/config/config.prod.yaml b/Server/user/config/config.prod.yaml new file mode 100644 index 0000000..524c7f7 --- /dev/null +++ b/Server/user/config/config.prod.yaml @@ -0,0 +1,27 @@ +app: + name: "user-prod" + +log: + debug: false + level: "debug" + maxSize: 10 + maxBackups: 100 + maxAge: 7 + +db: + etcd: + endpoints: [ "172.18.28.0:2379" ] + mysql: + user_db: + dsn: "root:gR9pV4tY7zR6qL3e@tcp(47.108.184.184:3306)/user_db?charset=utf8mb4&parseTime=True&loc=Local" + max_open_conn: 50 + max_idle_conn: 20 + conn_max_lifetime_sec: 600 + conn_max_idle_time_sec: 180 + log_level: "warn" + +serve: + grpc: + address: "172.18.28.0" + port: 8602 + ttl: 20 diff --git a/Server/user/go.mod b/Server/user/go.mod new file mode 100644 index 0000000..09893f5 --- /dev/null +++ b/Server/user/go.mod @@ -0,0 +1,57 @@ +module user + +go 1.23.1 + +require ( + common v0.0.0-00010101000000-000000000000 + github.com/judwhite/go-svc v1.2.1 + google.golang.org/grpc v1.71.1 + google.golang.org/protobuf v1.36.6 +) + +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/bwmarrin/snowflake v0.3.0 // indirect + github.com/coreos/go-semver v0.3.1 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/natefinch/lumberjack v2.0.0+incompatible // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/spf13/viper v1.21.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.etcd.io/etcd/api/v3 v3.6.1 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.6.1 // indirect + go.etcd.io/etcd/client/v3 v3.6.1 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/mod v0.26.0 // indirect + golang.org/x/net v0.42.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.34.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/tools v0.35.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect + gorm.io/datatypes v1.2.4 // indirect + gorm.io/driver/mysql v1.6.0 // indirect + gorm.io/gen v0.3.27 // indirect + gorm.io/gorm v1.31.1 // indirect + gorm.io/hints v1.1.0 // indirect + gorm.io/plugin/dbresolver v1.6.2 // indirect +) + +replace common => ../common diff --git a/Server/user/go.sum b/Server/user/go.sum new file mode 100644 index 0000000..cb21859 --- /dev/null +++ b/Server/user/go.sum @@ -0,0 +1,199 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= +github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= +github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +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/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= +github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +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/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/judwhite/go-svc v1.2.1 h1:a7fsJzYUa33sfDJRF2N/WXhA+LonCEEY8BJb1tuS5tA= +github.com/judwhite/go-svc v1.2.1/go.mod h1:mo/P2JNX8C07ywpP9YtO2gnBgnUiFTHqtsZekJrUuTk= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= +github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= +github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= +github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/etcd/api/v3 v3.6.1 h1:yJ9WlDih9HT457QPuHt/TH/XtsdN2tubyxyQHSHPsEo= +go.etcd.io/etcd/api/v3 v3.6.1/go.mod h1:lnfuqoGsXMlZdTJlact3IB56o3bWp1DIlXPIGKRArto= +go.etcd.io/etcd/client/pkg/v3 v3.6.1 h1:CxDVv8ggphmamrXM4Of8aCC8QHzDM4tGcVr9p2BSoGk= +go.etcd.io/etcd/client/pkg/v3 v3.6.1/go.mod h1:aTkCp+6ixcVTZmrJGa7/Mc5nMNs59PEgBbq+HCmWyMc= +go.etcd.io/etcd/client/v3 v3.6.1 h1:KelkcizJGsskUXlsxjVrSmINvMMga0VWwFF0tSPGEP0= +go.etcd.io/etcd/client/v3 v3.6.1/go.mod h1:fCbPUdjWNLfx1A6ATo9syUmFVxqHH9bCnPLBZmnLmMY= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +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/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +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-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= +google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= +google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/datatypes v1.2.4 h1:uZmGAcK/QZ0uyfCuVg0VQY1ZmV9h1fuG0tMwKByO1z4= +gorm.io/datatypes v1.2.4/go.mod h1:f4BsLcFAX67szSv8svwLRjklArSHAvHLeE3pXAS5DZI= +gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg= +gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo= +gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= +gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A= +gorm.io/driver/sqlite v1.1.6/go.mod h1:W8LmC/6UvVbHKah0+QOC7Ja66EaZXHwUTjgXY8YNWX8= +gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= +gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8= +gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= +gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig= +gorm.io/gen v0.3.27 h1:ziocAFLpE7e0g4Rum69pGfB9S6DweTxK8gAun7cU8as= +gorm.io/gen v0.3.27/go.mod h1:9zquz2xD1f3Eb/eHq4oLn2z6vDVvQlCY5S3uMBLv4EA= +gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= +gorm.io/gorm v1.22.2/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= +gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg= +gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= +gorm.io/hints v1.1.0 h1:Lp4z3rxREufSdxn4qmkK3TLDltrM10FLTHiuqwDPvXw= +gorm.io/hints v1.1.0/go.mod h1:lKQ0JjySsPBj3uslFzY3JhYDtqEwzm+G1hv8rWujB6Y= +gorm.io/plugin/dbresolver v1.6.2 h1:F4b85TenghUeITqe3+epPSUtHH7RIk3fXr5l83DF8Pc= +gorm.io/plugin/dbresolver v1.6.2/go.mod h1:tctw63jdrOezFR9HmrKnPkmig3m5Edem9fdxk9bQSzM= diff --git a/Public/Tools/mysql_model/dao/model/users.gen.go b/Server/user/internal/dao/model/users.gen.go similarity index 67% rename from Public/Tools/mysql_model/dao/model/users.gen.go rename to Server/user/internal/dao/model/users.gen.go index de2bc63..e5007d6 100644 --- a/Public/Tools/mysql_model/dao/model/users.gen.go +++ b/Server/user/internal/dao/model/users.gen.go @@ -5,18 +5,19 @@ package model import ( - "time" - + "common/utils" "gorm.io/gorm" + "time" ) const TableNameUser = "users" // User mapped from table type User struct { - ID int64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` - Sn string `gorm:"column:sn;not null;comment:业务唯一编号" json:"sn"` // 业务唯一编号 + ID uint64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` + Sn int64 `gorm:"column:sn;not null;comment:业务唯一编号" json:"sn"` // 业务唯一编号 Name string `gorm:"column:name;not null" json:"name"` + Phone string `gorm:"column:phone;not null" json:"phone"` CreatedAt time.Time `gorm:"column:created_at;not null" json:"created_at"` UpdatedAt time.Time `gorm:"column:updated_at;not null" json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"column:deleted_at" json:"deleted_at"` @@ -26,3 +27,11 @@ type User struct { func (*User) TableName() string { return TableNameUser } + +// auto sn +func (m *User) BeforeCreate(_ *gorm.DB) error { + if m.Sn == 0 { + m.Sn = utils.SnowflakeInstance().Generate().Int64() + } + return nil +} diff --git a/Server/common/db/mysql/point/query/gen.go b/Server/user/internal/dao/query/gen.go similarity index 100% rename from Server/common/db/mysql/point/query/gen.go rename to Server/user/internal/dao/query/gen.go diff --git a/Server/common/db/mysql/point/query/users.gen.go b/Server/user/internal/dao/query/users.gen.go similarity index 94% rename from Server/common/db/mysql/point/query/users.gen.go rename to Server/user/internal/dao/query/users.gen.go index b676a1b..5d757ed 100644 --- a/Server/common/db/mysql/point/query/users.gen.go +++ b/Server/user/internal/dao/query/users.gen.go @@ -5,8 +5,8 @@ package query import ( - "common/db/mysql/point/model" "context" + "user/internal/dao/model" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -26,9 +26,10 @@ func newUser(db *gorm.DB, opts ...gen.DOOption) user { tableName := _user.userDo.TableName() _user.ALL = field.NewAsterisk(tableName) - _user.ID = field.NewInt64(tableName, "id") - _user.Sn = field.NewString(tableName, "sn") + _user.ID = field.NewUint64(tableName, "id") + _user.Sn = field.NewInt64(tableName, "sn") _user.Name = field.NewString(tableName, "name") + _user.Phone = field.NewString(tableName, "phone") _user.CreatedAt = field.NewTime(tableName, "created_at") _user.UpdatedAt = field.NewTime(tableName, "updated_at") _user.DeletedAt = field.NewField(tableName, "deleted_at") @@ -42,9 +43,10 @@ type user struct { userDo userDo ALL field.Asterisk - ID field.Int64 - Sn field.String // 业务唯一编号 + ID field.Uint64 + Sn field.Int64 // 业务唯一编号 Name field.String + Phone field.String CreatedAt field.Time UpdatedAt field.Time DeletedAt field.Field @@ -64,9 +66,10 @@ func (u user) As(alias string) *user { func (u *user) updateTableName(table string) *user { u.ALL = field.NewAsterisk(table) - u.ID = field.NewInt64(table, "id") - u.Sn = field.NewString(table, "sn") + u.ID = field.NewUint64(table, "id") + u.Sn = field.NewInt64(table, "sn") u.Name = field.NewString(table, "name") + u.Phone = field.NewString(table, "phone") u.CreatedAt = field.NewTime(table, "created_at") u.UpdatedAt = field.NewTime(table, "updated_at") u.DeletedAt = field.NewField(table, "deleted_at") @@ -94,10 +97,11 @@ func (u *user) GetFieldByName(fieldName string) (field.OrderExpr, bool) { } func (u *user) fillFieldMap() { - u.fieldMap = make(map[string]field.Expr, 6) + u.fieldMap = make(map[string]field.Expr, 7) u.fieldMap["id"] = u.ID u.fieldMap["sn"] = u.Sn u.fieldMap["name"] = u.Name + u.fieldMap["phone"] = u.Phone u.fieldMap["created_at"] = u.CreatedAt u.fieldMap["updated_at"] = u.UpdatedAt u.fieldMap["deleted_at"] = u.DeletedAt diff --git a/Server/user/internal/dao/repository/users.go b/Server/user/internal/dao/repository/users.go new file mode 100644 index 0000000..bd5e6cd --- /dev/null +++ b/Server/user/internal/dao/repository/users.go @@ -0,0 +1,40 @@ +package repository + +import ( + "common/db/mysql" + "context" + "user/internal/dao/model" + "user/internal/dao/query" +) + +type UserDao struct { + ctx context.Context + query *query.Query +} + +func NewUserDao(ctx context.Context) *UserDao { + return &UserDao{ + ctx: ctx, + query: query.Use(mysql.GetDB("user_db")), + } +} + +func (d *UserDao) FindBySn(sn int64) (*model.User, error) { + first, err := d.query.User.WithContext(d.ctx). + Where(d.query.User.Sn.Eq(sn)). + First() + if err != nil { + return nil, err + } + return first, nil +} + +func (d *UserDao) FindByPhone(phone string) (*model.User, error) { + first, err := d.query.User.WithContext(d.ctx). + Where(d.query.User.Phone.Eq(phone)). + First() + if err != nil { + return nil, err + } + return first, nil +} diff --git a/Server/user/internal/grpc_server/server/server.go b/Server/user/internal/grpc_server/server/server.go new file mode 100644 index 0000000..fb9caa0 --- /dev/null +++ b/Server/user/internal/grpc_server/server/server.go @@ -0,0 +1,21 @@ +package server + +import ( + "common/log" + "common/proto/ss/grpc_pb" + "context" + "user/internal/dao/repository" +) + +func (s *Server) Login(ctx context.Context, req *grpc_pb.LoginReq) (*grpc_pb.LoginResp, error) { + log.Infof("Login req: %+v", req) + + user, err := repository.NewUserDao(ctx).FindBySn(857527344353) + if err != nil { + return nil, err + } + + return &grpc_pb.LoginResp{ + UID: int32(user.Sn), + }, nil +} diff --git a/Server/user/internal/grpc_server/server/server_init.go b/Server/user/internal/grpc_server/server/server_init.go new file mode 100644 index 0000000..2cea096 --- /dev/null +++ b/Server/user/internal/grpc_server/server/server_init.go @@ -0,0 +1,32 @@ +package server + +import ( + "common/discover/common" + "common/net/grpc/service" + "common/proto/ss/grpc_pb" + "google.golang.org/grpc" +) + +type Server struct { + grpc_pb.UnimplementedUserServer + service.Base +} + +func NewServer(ttl int64) *Server { + s := &Server{ + Base: service.Base{ + Target: common.KeyDiscoverUser, + EtcdTTL: ttl, + }, + } + s.Base.OnInit = s.OnInit + s.Base.OnClose = s.OnClose + return s +} + +func (s *Server) OnInit(serve *grpc.Server) { + grpc_pb.RegisterUserServer(serve, s) +} + +func (s *Server) OnClose() { +} diff --git a/Server/user/internal/grpc_server/stream_client/gateway.go b/Server/user/internal/grpc_server/stream_client/gateway.go new file mode 100644 index 0000000..fd735ee --- /dev/null +++ b/Server/user/internal/grpc_server/stream_client/gateway.go @@ -0,0 +1,65 @@ +package stream_client + +import ( + "common/log" + "common/net/grpc/service" + "context" + "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +var gatewayServerM map[int64]map[GatewayFun]grpc.ClientStream // map[sid]map[方法名]流连接 + +type GatewayFun int + +const ( + FunToClient GatewayFun = iota +) + +func init() { + gatewayServerM = make(map[int64]map[GatewayFun]grpc.ClientStream) +} + +func FindGatewayBySID(sid int64, fun GatewayFun) (grpc.ClientStream, error) { + g := gatewayServerM[sid] + if g == nil { + g = make(map[GatewayFun]grpc.ClientStream) + gatewayServerM[sid] = g + } + gatewayLink := g[fun] + if gatewayLink == nil { + gatewayClient, err := service.GatewayNewClient(sid) + if err != nil { + log.Errorf("cannot find gatewayClient: %v", err) + return nil, err + } + var link grpc.ClientStream + switch fun { + case FunToClient: + link, err = gatewayClient.ToClient(context.Background()) + } + if err != nil { + log.Errorf("FindGatewayBySID %v err: %v, sid: %v", fun, err, sid) + return nil, err + } + g[fun] = link + gatewayLink = link + } + return gatewayLink, nil +} + +func SendMessageToGateway(sid int64, fun GatewayFun, msg proto.Message, re ...bool) error { + stream, err := FindGatewayBySID(sid, fun) + if err != nil { + return err + } + if err = stream.SendMsg(msg); err != nil { + if re == nil || !re[0] { + _ = stream.CloseSend() + delete(gatewayServerM[sid], fun) + return SendMessageToGateway(sid, fun, msg, true) + } + return err + } + return nil +} diff --git a/Server/user/main.go b/Server/user/main.go new file mode 100644 index 0000000..57c43fa --- /dev/null +++ b/Server/user/main.go @@ -0,0 +1,14 @@ +package main + +import ( + "fmt" + "github.com/judwhite/go-svc" + "syscall" + "user/app" +) + +func main() { + if err := svc.Run(&app.Program{}, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL); err != nil { + fmt.Println(err) + } +} diff --git a/Server/指导方针.md b/Server/指导方针.md new file mode 100644 index 0000000..2dd4f7b --- /dev/null +++ b/Server/指导方针.md @@ -0,0 +1,176 @@ +太棒了!你已经抓住了微服务的核心痛点(数据库隔离、分层架构、服务边界),接下来我们系统性地梳理 **构建真正可靠、可维护、可演进的微服务架构必须遵守的关键原则**。 + +--- + +## ✅ 微服务十大核心原则(实战导向) + +> 这些不是理论教条,而是无数团队踩坑后总结出的“生存法则”。 + +--- + +### 1. **单一职责 & 高内聚(Single Responsibility)** +- 每个微服务应围绕 **一个明确的业务能力**(如“用户管理”、“支付”、“通知”)。 +- ❌ 不要按技术分层拆服务(如“所有 DB 服务”、“所有 API 服务”)。 +- ✅ 建议用 **DDD(领域驱动设计)** 划分限界上下文(Bounded Context)。 + +> 📌 口诀:**“一个服务,一个事”** + +--- + +### 2. **自治性(Autonomy)** +- 服务应能 **独立开发、测试、部署、扩展、故障恢复**。 +- 依赖越少越好;跨服务调用必须有 **降级、熔断、超时** 机制。 +- 使用 **契约测试(Contract Testing)** 保证接口兼容(如 Pact)。 + +> 🔧 工具推荐: +> - gRPC + Protobuf(强契约) +> - OpenAPI(REST) +> - WireMock / Pact(契约测试) + +--- + +### 3. **数据私有(Database per Service)** ← 你已掌握! +- 每个服务独占数据存储,**禁止跨服务直连数据库**。 +- 跨服务数据交互靠: + - **同步**:API(gRPC/HTTP) + - **异步**:事件(Kafka / RabbitMQ / Pulsar) + +> 💡 技巧:用 **事件溯源(Event Sourcing) + CQRS** 构建复杂查询视图。 + +--- + +### 4. **无状态(Stateless)** +- 服务实例本身不保存会话或状态(状态存 Redis / DB / Cookie)。 +- 好处:**水平扩展容易**,K8s 可随意扩缩容。 + +> ⚠️ 例外:批处理、流计算等有状态场景可用 StatefulSet,但要谨慎。 + +--- + +### 5. **可观测性(Observability)三件套** +微服务没有可观测性 = 盲人开车! + +| 组件 | 作用 | 工具推荐 | +|------|------|--------| +| **Logging** | 记录结构化日志 | Zap / Logrus + Loki / ELK | +| **Metrics** | 监控性能指标 | Prometheus + Grafana | +| Assistant | 追踪请求链路 | Jaeger / Zipkin / OpenTelemetry | + +> ✅ 必做: +> - 所有日志带 `trace_id` +> - 所有 gRPC 调用自动埋点 +> - 关键路径加自定义指标(如“登录成功率”) + +--- + +### 6. **弹性设计(Resilience)** +网络不可靠!必须假设: +- 其他服务会宕机 +- 网络会延迟或丢包 + +✅ 必备机制: +- **超时(Timeout)**:每个调用设上限(如 1s) +- **重试(Retry)**:带退避策略(指数退避) +- **熔断(Circuit Breaker)**:失败太多就短路(如 Hystrix / Sentinel) +- **限流(Rate Limiting)**:保护自己不被压垮 +- **降级(Fallback)**:返回默认值或缓存数据 + +> 🛠 Go 推荐库: +> - `go-resiliency` +> - `sony/gobreaker` +> - 自研中间件(结合 context + retry) + +--- + +### 7. **API 优先(API-First Design)** +- 先定义 `.proto`(gRPC)或 OpenAPI(REST),再写代码。 +- 客户端 SDK 自动生成(如 `protoc-gen-go`)。 +- 版本管理:**向后兼容优先**,避免频繁改接口。 + +> 📁 目录建议: +> ``` +> api/ +> ├── user/v1/user.proto +> └── order/v1/order.proto +> ``` + +--- + +### 8. **基础设施即代码(IaC) & GitOps** +- 数据库、K8s、网关配置全部代码化(Terraform / Helm / Kustomize)。 +- 所有变更通过 Git PR 触发自动化部署。 +- 环境一致性:dev / staging / prod 配置几乎相同。 + +> ✅ 好处:**“一键重建整个环境”** + +--- + +### 9. **安全内建(Security by Default)** +- **mTLS**:服务间通信加密(Istio / Linkerd) +- **RBAC**:基于角色的访问控制 +- **敏感信息**:用 Vault / K8s Secret 管理,不硬编码 +- **输入校验**:所有 API 参数严格验证(如 `validator.v10`) + +> 🔒 原则:**“零信任网络”** —— 不信任任何内部流量。 + +--- + +### 10. **演进式设计(Evolutionary Architecture)** +- 不追求“一次性完美架构” +- 用 **Strangler Fig Pattern(绞杀者模式)** 逐步替换旧系统 +- 定期做 **架构重构** 和 **技术债清理** + +> 🌱 微服务是“种出来的”,不是“画出来的”。 + +--- + +## 🧱 推荐架构分层(Go 微服务) + +``` +user-service/ +├── api/ # .proto 文件(对外契约) +├── cmd/ # main 入口 +├── internal/ +│ ├── handler/ # gRPC/HTTP handlers(薄层) +│ ├── service/ # 业务逻辑(核心) +│ ├── repository/ # 数据访问(接口 + mysql 实现) +│ └── model/ # 领域模型(与 DB 解耦) +├── pkg/ # 可共享工具(谨慎!) +├── deploy/ # K8s / Docker 配置 +└── go.mod +``` + +> 🔑 关键:`internal/` 禁止被外部 import,强制通过 API 交互。 + +--- + +## 🚫 微服务常见反模式(务必避开!) + +| 反模式 | 后果 | +|-------|------| +| 分布式单体 | 失去微服务所有优势 | +| 共享数据库 | 强耦合,无法独立演进 | +| 同步调用链过长(A→B→C→D) | 故障放大,雪崩风险 | +| 无监控无告警 | 出问题找不到原因 | +| 手动部署 | 发布慢,易出错 | + +--- + +## ✅ 最后建议:从小做起,逐步完善 + +1. **先保证“能跑”**:一个服务 + 独立 DB + gRPC API +2. **加上可观测性**:日志 + Metrics + Tracing +3. **加上弹性机制**:超时 + 重试 +4. **加上 CI/CD**:自动化测试 & 部署 +5. **再考虑事件驱动、CQRS、Service Mesh...** + +> 🌟 **好的微服务架构不是设计出来的,而是在约束和实践中演化出来的。** + +--- + +如果你愿意,我可以: +- 帮你画一张 **典型微服务架构图** +- 提供一个 **Go 微服务模板项目结构** +- 推荐 **K8s + Istio + Prometheus 的最小可行部署方案** + +祝你打造出**真正可靠、优雅、可演进**的微服务系统!🚀 \ No newline at end of file