Compare commits
93 Commits
Author | SHA1 | Date | |
---|---|---|---|
786bbb7185 | |||
95207c9617 | |||
d646deb468 | |||
468819f0a0 | |||
832f1034a8 | |||
f0b6370ee1 | |||
3d522b094b | |||
92dcd1acd7 | |||
dc8a736e13 | |||
|
4219919c9e | ||
1f447ea747 | |||
|
30c0e01397 | ||
244f3def4d | |||
|
55cbc89e11 | ||
df00f718cf | |||
|
bc3369f3a6 | ||
8d4c661ce5 | |||
|
7b97212e26 | ||
|
9d5a2c1168 | ||
|
483c6bb801 | ||
|
7ba5fd5fee | ||
080705a5df | |||
|
79df512e5e | ||
|
3e893b78c8 | ||
8e9c64d78b | |||
|
d66aa424d2 | ||
|
f8d3695962 | ||
ae158ce5fc | |||
8125c9003c | |||
a6f6df257b | |||
6b19cb2fb7 | |||
|
db6fee9760 | ||
309f100532 | |||
|
22ae55f739 | ||
70700a3f86 | |||
7dd327086c | |||
a67efa39ae | |||
|
8ee91422cc | ||
f8ae500c5f | |||
|
7fcc042fbf | ||
3a22f3a900 | |||
|
452a124aee | ||
|
26d3adfe95 | ||
|
18d6584c8f | ||
f26dde5d63 | |||
|
66d3feb263 | ||
5c8effa23f | |||
|
c1e318d0b3 | ||
617764706c | |||
0f3e56f697 | |||
|
b87462c465 | ||
|
e877a92718 | ||
|
c60f0ccb26 | ||
7cf4a8d293 | |||
84b1b862a7 | |||
|
eb17921feb | ||
|
ddeb0a23c3 | ||
|
830d8d8fda | ||
|
ceaff6bf88 | ||
|
01848b8ec7 | ||
|
8ddfa39811 | ||
110a8a8a9c | |||
|
f2587f0876 | ||
eccdad9752 | |||
|
c05996ee6e | ||
734d6fa7af | |||
4c0ca3664a | |||
|
d34ce4f314 | ||
|
d9932033ee | ||
847887de84 | |||
|
10ea1928f4 | ||
|
52d37c6579 | ||
|
0af18ab84b | ||
|
c46d11a2d4 | ||
|
117f48aac5 | ||
b4a2fbdeeb | |||
e36db68d4d | |||
b6b101b140 | |||
cbafc74e41 | |||
1e19359ab1 | |||
8e88abbbca | |||
adf9a0d82d | |||
a1a5980534 | |||
25a74b6935 | |||
|
5ed755f5bb | ||
8dd303472d | |||
|
1f6b2b34ec | ||
ce3da2c9fa | |||
b248593e35 | |||
|
dda5d46e47 | ||
0f50e30f9c | |||
|
f983ccc6d9 | ||
|
ef9ee6d837 |
2
.github/workflows/autoapprove.yml
vendored
2
.github/workflows/autoapprove.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: approve
|
- name: approve
|
||||||
uses: hmarr/auto-approve-action@v2
|
uses: hmarr/auto-approve-action@v3
|
||||||
if: github.actor == 'vtolstov' || github.actor == 'dependabot[bot]'
|
if: github.actor == 'vtolstov' || github.actor == 'dependabot[bot]'
|
||||||
id: approve
|
id: approve
|
||||||
with:
|
with:
|
||||||
|
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -10,13 +10,13 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: setup
|
- name: setup
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: 1.17
|
go-version: 1.17
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: cache
|
- name: cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/go/pkg/mod
|
path: ~/go/pkg/mod
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: lint
|
- name: lint
|
||||||
uses: golangci/golangci-lint-action@v3.1.0
|
uses: golangci/golangci-lint-action@v3.4.0
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
||||||
|
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
@@ -45,12 +45,12 @@ jobs:
|
|||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: setup
|
- name: setup
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: 1.17
|
go-version: 1.17
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: init
|
- name: init
|
||||||
uses: github/codeql-action/init@v1
|
uses: github/codeql-action/init@v2
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@@ -61,7 +61,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: autobuild
|
- name: autobuild
|
||||||
uses: github/codeql-action/autobuild@v1
|
uses: github/codeql-action/autobuild@v2
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
@@ -75,4 +75,4 @@ jobs:
|
|||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: analyze
|
- name: analyze
|
||||||
uses: github/codeql-action/analyze@v1
|
uses: github/codeql-action/analyze@v2
|
||||||
|
2
.github/workflows/dependabot-automerge.yml
vendored
2
.github/workflows/dependabot-automerge.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: metadata
|
- name: metadata
|
||||||
id: metadata
|
id: metadata
|
||||||
uses: dependabot/fetch-metadata@v1.3.0
|
uses: dependabot/fetch-metadata@v1.3.6
|
||||||
with:
|
with:
|
||||||
github-token: "${{ secrets.TOKEN }}"
|
github-token: "${{ secrets.TOKEN }}"
|
||||||
- name: merge
|
- name: merge
|
||||||
|
6
.github/workflows/pr.yml
vendored
6
.github/workflows/pr.yml
vendored
@@ -10,13 +10,13 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: setup
|
- name: setup
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: 1.17
|
go-version: 1.17
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: cache
|
- name: cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/go/pkg/mod
|
path: ~/go/pkg/mod
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: lint
|
- name: lint
|
||||||
uses: golangci/golangci-lint-action@v3.1.0
|
uses: golangci/golangci-lint-action@v3.4.0
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
||||||
|
8
go.mod
8
go.mod
@@ -4,8 +4,8 @@ go 1.16
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golang/protobuf v1.5.2
|
github.com/golang/protobuf v1.5.2
|
||||||
go.unistack.org/micro/v3 v3.9.0
|
go.unistack.org/micro/v3 v3.10.14
|
||||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b
|
golang.org/x/net v0.5.0
|
||||||
google.golang.org/grpc v1.45.0
|
google.golang.org/grpc v1.52.3
|
||||||
google.golang.org/protobuf v1.27.1
|
google.golang.org/protobuf v1.28.1
|
||||||
)
|
)
|
||||||
|
241
grpc.go
241
grpc.go
@@ -26,7 +26,6 @@ import (
|
|||||||
"golang.org/x/net/netutil"
|
"golang.org/x/net/netutil"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/credentials"
|
|
||||||
"google.golang.org/grpc/encoding"
|
"google.golang.org/grpc/encoding"
|
||||||
gmetadata "google.golang.org/grpc/metadata"
|
gmetadata "google.golang.org/grpc/metadata"
|
||||||
"google.golang.org/grpc/peer"
|
"google.golang.org/grpc/peer"
|
||||||
@@ -35,17 +34,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultContentType = "application/grpc+proto"
|
DefaultContentType = "application/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
type grpcServerReflection struct {
|
type ServerReflection struct {
|
||||||
srv *grpc.Server
|
srv *grpc.Server
|
||||||
s *serverReflectionServer
|
s *serverReflectionServer
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type grpcServer struct {
|
type Server struct {
|
||||||
handlers map[string]server.Handler
|
handlers map[string]server.Handler
|
||||||
srv *grpc.Server
|
srv *grpc.Server
|
||||||
exit chan chan error
|
exit chan chan error
|
||||||
@@ -55,15 +54,14 @@ type grpcServer struct {
|
|||||||
rpc *rServer
|
rpc *rServer
|
||||||
opts server.Options
|
opts server.Options
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
init bool
|
|
||||||
started bool
|
started bool
|
||||||
registered bool
|
registered bool
|
||||||
reflection bool
|
reflection bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGRPCServer(opts ...server.Option) server.Server {
|
func newServer(opts ...server.Option) *Server {
|
||||||
// create a grpc server
|
// create a grpc server
|
||||||
g := &grpcServer{
|
g := &Server{
|
||||||
opts: server.NewOptions(opts...),
|
opts: server.NewOptions(opts...),
|
||||||
rpc: &rServer{
|
rpc: &rServer{
|
||||||
serviceMap: make(map[string]*service),
|
serviceMap: make(map[string]*service),
|
||||||
@@ -92,7 +90,7 @@ func (r grpcRouter) ServeRequest(ctx context.Context, req server.Request, rsp se
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func (g *grpcServer) configure(opts ...server.Option) error {
|
func (g *Server) configure(opts ...server.Option) error {
|
||||||
g.Lock()
|
g.Lock()
|
||||||
defer g.Unlock()
|
defer g.Unlock()
|
||||||
|
|
||||||
@@ -109,9 +107,6 @@ func (g *grpcServer) configure(opts ...server.Option) error {
|
|||||||
if err := g.opts.Tracer.Init(); err != nil {
|
if err := g.opts.Tracer.Init(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := g.opts.Auth.Init(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := g.opts.Logger.Init(); err != nil {
|
if err := g.opts.Logger.Init(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -132,6 +127,10 @@ func (g *grpcServer) configure(opts ...server.Option) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, k := range g.opts.Codecs {
|
||||||
|
encoding.RegisterCodec(&wrapMicroCodec{k})
|
||||||
|
}
|
||||||
|
|
||||||
maxMsgSize := g.getMaxMsgSize()
|
maxMsgSize := g.getMaxMsgSize()
|
||||||
|
|
||||||
gopts := []grpc.ServerOption{
|
gopts := []grpc.ServerOption{
|
||||||
@@ -140,12 +139,8 @@ func (g *grpcServer) configure(opts ...server.Option) error {
|
|||||||
grpc.UnknownServiceHandler(g.handler),
|
grpc.UnknownServiceHandler(g.handler),
|
||||||
}
|
}
|
||||||
|
|
||||||
if creds := g.getCredentials(); creds != nil {
|
|
||||||
gopts = append(gopts, grpc.Creds(creds))
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts := g.getGrpcOptions(); opts != nil {
|
if opts := g.getGrpcOptions(); opts != nil {
|
||||||
gopts = append(gopts, opts...)
|
gopts = append(opts, gopts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.rsvc = nil
|
g.rsvc = nil
|
||||||
@@ -166,12 +161,10 @@ func (g *grpcServer) configure(opts ...server.Option) error {
|
|||||||
return g.Start()
|
return g.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
g.init = true
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) getMaxMsgSize() int {
|
func (g *Server) getMaxMsgSize() int {
|
||||||
if g.opts.Context == nil {
|
if g.opts.Context == nil {
|
||||||
return codec.DefaultMaxMsgSize
|
return codec.DefaultMaxMsgSize
|
||||||
}
|
}
|
||||||
@@ -182,14 +175,7 @@ func (g *grpcServer) getMaxMsgSize() int {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) getCredentials() credentials.TransportCredentials {
|
func (g *Server) getGrpcOptions() []grpc.ServerOption {
|
||||||
if g.opts.TLSConfig != nil {
|
|
||||||
return credentials.NewTLS(g.opts.TLSConfig)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *grpcServer) getGrpcOptions() []grpc.ServerOption {
|
|
||||||
if g.opts.Context == nil {
|
if g.opts.Context == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -202,32 +188,7 @@ func (g *grpcServer) getGrpcOptions() []grpc.ServerOption {
|
|||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) (err error) {
|
func (g *Server) handler(srv interface{}, stream grpc.ServerStream) (err error) {
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
g.RLock()
|
|
||||||
config := g.opts
|
|
||||||
g.RUnlock()
|
|
||||||
if config.Logger.V(logger.ErrorLevel) {
|
|
||||||
config.Logger.Error(config.Context, "panic recovered: ", r)
|
|
||||||
config.Logger.Error(config.Context, string(debug.Stack()))
|
|
||||||
}
|
|
||||||
err = errors.InternalServerError(g.opts.Name, "panic recovered: %v", r)
|
|
||||||
} else if err != nil {
|
|
||||||
g.RLock()
|
|
||||||
config := g.opts
|
|
||||||
g.RUnlock()
|
|
||||||
if config.Logger.V(logger.ErrorLevel) {
|
|
||||||
config.Logger.Errorf(config.Context, "grpc handler got error: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if g.wg != nil {
|
|
||||||
g.wg.Add(1)
|
|
||||||
defer g.wg.Done()
|
|
||||||
}
|
|
||||||
|
|
||||||
fullMethod, ok := grpc.MethodFromServerStream(stream)
|
fullMethod, ok := grpc.MethodFromServerStream(stream)
|
||||||
if !ok {
|
if !ok {
|
||||||
return status.Errorf(codes.Internal, "method does not exist in context")
|
return status.Errorf(codes.Internal, "method does not exist in context")
|
||||||
@@ -238,6 +199,31 @@ func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) (err err
|
|||||||
return status.New(codes.InvalidArgument, err.Error()).Err()
|
return status.New(codes.InvalidArgument, err.Error()).Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
g.RLock()
|
||||||
|
config := g.opts
|
||||||
|
g.RUnlock()
|
||||||
|
if config.Logger.V(logger.ErrorLevel) {
|
||||||
|
config.Logger.Errorf(config.Context, "panic in %s.%s recovered: %v", serviceName, methodName, r)
|
||||||
|
config.Logger.Error(config.Context, string(debug.Stack()))
|
||||||
|
}
|
||||||
|
err = errors.InternalServerError(g.opts.Name, "panic in %s.%s recovered: %v", serviceName, methodName, r)
|
||||||
|
} else if err != nil {
|
||||||
|
g.RLock()
|
||||||
|
config := g.opts
|
||||||
|
g.RUnlock()
|
||||||
|
if config.Logger.V(logger.ErrorLevel) {
|
||||||
|
config.Logger.Errorf(config.Context, "grpc handler %s.%s got error: %s", serviceName, methodName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if g.wg != nil {
|
||||||
|
g.wg.Add(1)
|
||||||
|
defer g.wg.Done()
|
||||||
|
}
|
||||||
|
|
||||||
// get grpc metadata
|
// get grpc metadata
|
||||||
gmd, ok := gmetadata.FromIncomingContext(stream.Context())
|
gmd, ok := gmetadata.FromIncomingContext(stream.Context())
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -258,7 +244,7 @@ func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) (err err
|
|||||||
if v, ok := md.Get("Grpc-Timeout"); ok {
|
if v, ok := md.Get("Grpc-Timeout"); ok {
|
||||||
md.Del("Grpc-Timeout")
|
md.Del("Grpc-Timeout")
|
||||||
td = v[:len(v)-1]
|
td = v[:len(v)-1]
|
||||||
switch v[:] {
|
switch v[len(v)-1:] {
|
||||||
case "S":
|
case "S":
|
||||||
td += "s"
|
td += "s"
|
||||||
case "M":
|
case "M":
|
||||||
@@ -289,7 +275,7 @@ func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) (err err
|
|||||||
|
|
||||||
// get peer from context
|
// get peer from context
|
||||||
if p, ok := peer.FromContext(stream.Context()); ok {
|
if p, ok := peer.FromContext(stream.Context()); ok {
|
||||||
md["Remote"] = p.Addr.String()
|
md.Set("Remote", p.Addr.String())
|
||||||
ctx = peer.NewContext(ctx, p)
|
ctx = peer.NewContext(ctx, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +294,7 @@ func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) (err err
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
if svc == nil && g.reflection && methodName == "ServerReflectionInfo" {
|
if svc == nil && g.reflection && methodName == "ServerReflectionInfo" {
|
||||||
rfl := &grpcServerReflection{srv: g.srv, s: &serverReflectionServer{s: g.srv}}
|
rfl := &ServerReflection{srv: g.srv, s: &serverReflectionServer{s: g.srv}}
|
||||||
svc = &service{}
|
svc = &service{}
|
||||||
svc.typ = reflect.TypeOf(rfl)
|
svc.typ = reflect.TypeOf(rfl)
|
||||||
svc.rcvr = reflect.ValueOf(rfl)
|
svc.rcvr = reflect.ValueOf(rfl)
|
||||||
@@ -329,12 +315,22 @@ func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) (err err
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if svc == nil {
|
if svc == nil {
|
||||||
|
if g.opts.Context != nil {
|
||||||
|
if h, ok := g.opts.Context.Value(unknownServiceHandlerKey{}).(grpc.StreamHandler); ok {
|
||||||
|
return h(srv, stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
return status.New(codes.Unimplemented, fmt.Sprintf("unknown service %s", serviceName)).Err()
|
return status.New(codes.Unimplemented, fmt.Sprintf("unknown service %s", serviceName)).Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
mtype := svc.method[methodName]
|
mtype := svc.method[methodName]
|
||||||
if mtype == nil {
|
if mtype == nil {
|
||||||
return status.New(codes.Unimplemented, fmt.Sprintf("unknown service %s.%s", serviceName, methodName)).Err()
|
if g.opts.Context != nil {
|
||||||
|
if h, ok := g.opts.Context.Value(unknownServiceHandlerKey{}).(grpc.StreamHandler); ok {
|
||||||
|
return h(srv, stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status.New(codes.Unimplemented, fmt.Sprintf("unknown service method %s.%s", serviceName, methodName)).Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// process unary
|
// process unary
|
||||||
@@ -346,7 +342,7 @@ func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) (err err
|
|||||||
return g.processStream(ctx, stream, svc, mtype, ct)
|
return g.processStream(ctx, stream, svc, mtype, ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) processRequest(ctx context.Context, stream grpc.ServerStream, service *service, mtype *methodType, ct string) error {
|
func (g *Server) processRequest(ctx context.Context, stream grpc.ServerStream, service *service, mtype *methodType, ct string) error {
|
||||||
// for {
|
// for {
|
||||||
var err error
|
var err error
|
||||||
var argv, replyv reflect.Value
|
var argv, replyv reflect.Value
|
||||||
@@ -361,8 +357,7 @@ func (g *grpcServer) processRequest(ctx context.Context, stream grpc.ServerStrea
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal request
|
// Unmarshal request
|
||||||
// TODO: avoid Marshal call later by recv to frame and reuse it data
|
if err = stream.RecvMsg(argv.Interface()); err != nil {
|
||||||
if err := stream.RecvMsg(argv.Interface()); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,11 +376,12 @@ func (g *grpcServer) processRequest(ctx context.Context, stream grpc.ServerStrea
|
|||||||
service: g.opts.Name,
|
service: g.opts.Name,
|
||||||
contentType: ct,
|
contentType: ct,
|
||||||
method: fmt.Sprintf("%s.%s", service.name, mtype.method.Name),
|
method: fmt.Sprintf("%s.%s", service.name, mtype.method.Name),
|
||||||
|
endpoint: fmt.Sprintf("%s.%s", service.name, mtype.method.Name),
|
||||||
payload: argv.Interface(),
|
payload: argv.Interface(),
|
||||||
}
|
}
|
||||||
// define the handler func
|
// define the handler func
|
||||||
fn := func(ctx context.Context, req server.Request, rsp interface{}) (err error) {
|
fn := func(ctx context.Context, req server.Request, rsp interface{}) (err error) {
|
||||||
returnValues = function.Call([]reflect.Value{service.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(argv.Interface()), reflect.ValueOf(rsp)})
|
returnValues = function.Call([]reflect.Value{service.rcvr, mtype.prepareContext(ctx), argv, reflect.ValueOf(rsp)})
|
||||||
|
|
||||||
// The return value for the method is an error.
|
// The return value for the method is an error.
|
||||||
if rerr := returnValues[0].Interface(); rerr != nil {
|
if rerr := returnValues[0].Interface(); rerr != nil {
|
||||||
@@ -403,7 +399,13 @@ func (g *grpcServer) processRequest(ctx context.Context, stream grpc.ServerStrea
|
|||||||
statusCode := codes.OK
|
statusCode := codes.OK
|
||||||
statusDesc := ""
|
statusDesc := ""
|
||||||
// execute the handler
|
// execute the handler
|
||||||
if appErr := fn(ctx, r, replyv.Interface()); appErr != nil {
|
appErr := fn(ctx, r, replyv.Interface())
|
||||||
|
if outmd, ok := metadata.FromOutgoingContext(ctx); ok {
|
||||||
|
if err = stream.SendHeader(gmetadata.New(outmd)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if appErr != nil {
|
||||||
var errStatus *status.Status
|
var errStatus *status.Status
|
||||||
switch verr := appErr.(type) {
|
switch verr := appErr.(type) {
|
||||||
case *errors.Error:
|
case *errors.Error:
|
||||||
@@ -418,6 +420,8 @@ func (g *grpcServer) processRequest(ctx context.Context, stream grpc.ServerStrea
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case (interface{ GRPCStatus() *status.Status }):
|
||||||
|
errStatus = verr.GRPCStatus()
|
||||||
default:
|
default:
|
||||||
g.RLock()
|
g.RLock()
|
||||||
config := g.opts
|
config := g.opts
|
||||||
@@ -481,18 +485,19 @@ func (s *reflectStream) RecvMsg(m interface{}) error {
|
|||||||
return s.stream.Recv(m)
|
return s.stream.Recv(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServerReflection) ServerReflectionInfo(ctx context.Context, stream server.Stream) error {
|
func (g *ServerReflection) ServerReflectionInfo(ctx context.Context, stream server.Stream) error {
|
||||||
return g.s.ServerReflectionInfo(&reflectStream{stream})
|
return g.s.ServerReflectionInfo(&reflectStream{stream})
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func (g *grpcServer) processStream(ctx context.Context, stream grpc.ServerStream, service *service, mtype *methodType, ct string) error {
|
func (g *Server) processStream(ctx context.Context, stream grpc.ServerStream, service *service, mtype *methodType, ct string) error {
|
||||||
opts := g.opts
|
opts := g.opts
|
||||||
|
|
||||||
r := &rpcRequest{
|
r := &rpcRequest{
|
||||||
service: opts.Name,
|
service: opts.Name,
|
||||||
contentType: ct,
|
contentType: ct,
|
||||||
method: fmt.Sprintf("%s.%s", service.name, mtype.method.Name),
|
method: fmt.Sprintf("%s.%s", service.name, mtype.method.Name),
|
||||||
|
endpoint: fmt.Sprintf("%s.%s", service.name, mtype.method.Name),
|
||||||
stream: true,
|
stream: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,7 +526,13 @@ func (g *grpcServer) processStream(ctx context.Context, stream grpc.ServerStream
|
|||||||
statusCode := codes.OK
|
statusCode := codes.OK
|
||||||
statusDesc := ""
|
statusDesc := ""
|
||||||
|
|
||||||
if appErr := fn(ctx, r, ss); appErr != nil {
|
appErr := fn(ctx, r, ss)
|
||||||
|
if outmd, ok := metadata.FromOutgoingContext(ctx); ok {
|
||||||
|
if err := stream.SendHeader(gmetadata.New(outmd)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if appErr != nil {
|
||||||
var err error
|
var err error
|
||||||
var errStatus *status.Status
|
var errStatus *status.Status
|
||||||
switch verr := appErr.(type) {
|
switch verr := appErr.(type) {
|
||||||
@@ -553,7 +564,7 @@ func (g *grpcServer) processStream(ctx context.Context, stream grpc.ServerStream
|
|||||||
return status.New(statusCode, statusDesc).Err()
|
return status.New(statusCode, statusDesc).Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) newCodec(ct string) (codec.Codec, error) {
|
func (g *Server) newCodec(ct string) (codec.Codec, error) {
|
||||||
g.RLock()
|
g.RLock()
|
||||||
defer g.RUnlock()
|
defer g.RUnlock()
|
||||||
|
|
||||||
@@ -568,7 +579,7 @@ func (g *grpcServer) newCodec(ct string) (codec.Codec, error) {
|
|||||||
return nil, codec.ErrUnknownContentType
|
return nil, codec.ErrUnknownContentType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) Options() server.Options {
|
func (g *Server) Options() server.Options {
|
||||||
g.RLock()
|
g.RLock()
|
||||||
opts := g.opts
|
opts := g.opts
|
||||||
g.RUnlock()
|
g.RUnlock()
|
||||||
@@ -576,18 +587,15 @@ func (g *grpcServer) Options() server.Options {
|
|||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) Init(opts ...server.Option) error {
|
func (g *Server) Init(opts ...server.Option) error {
|
||||||
if len(opts) == 0 && g.init {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return g.configure(opts...)
|
return g.configure(opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) NewHandler(h interface{}, opts ...server.HandlerOption) server.Handler {
|
func (g *Server) NewHandler(h interface{}, opts ...server.HandlerOption) server.Handler {
|
||||||
return newRPCHandler(h, opts...)
|
return newRPCHandler(h, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) Handle(h server.Handler) error {
|
func (g *Server) Handle(h server.Handler) error {
|
||||||
if err := g.rpc.register(h.Handler()); err != nil {
|
if err := g.rpc.register(h.Handler()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -596,11 +604,11 @@ func (g *grpcServer) Handle(h server.Handler) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) NewSubscriber(topic string, sb interface{}, opts ...server.SubscriberOption) server.Subscriber {
|
func (g *Server) NewSubscriber(topic string, sb interface{}, opts ...server.SubscriberOption) server.Subscriber {
|
||||||
return newSubscriber(topic, sb, opts...)
|
return newSubscriber(topic, sb, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) Subscribe(sb server.Subscriber) error {
|
func (g *Server) Subscribe(sb server.Subscriber) error {
|
||||||
sub, ok := sb.(*subscriber)
|
sub, ok := sb.(*subscriber)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("invalid subscriber: expected *subscriber")
|
return fmt.Errorf("invalid subscriber: expected *subscriber")
|
||||||
@@ -624,7 +632,7 @@ func (g *grpcServer) Subscribe(sb server.Subscriber) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) Register() error {
|
func (g *Server) Register() error {
|
||||||
g.RLock()
|
g.RLock()
|
||||||
rsvc := g.rsvc
|
rsvc := g.rsvc
|
||||||
config := g.opts
|
config := g.opts
|
||||||
@@ -698,37 +706,13 @@ func (g *grpcServer) Register() error {
|
|||||||
g.Lock()
|
g.Lock()
|
||||||
defer g.Unlock()
|
defer g.Unlock()
|
||||||
|
|
||||||
for sb := range g.subscribers {
|
|
||||||
handler := g.createSubHandler(sb, config)
|
|
||||||
var opts []broker.SubscribeOption
|
|
||||||
if queue := sb.Options().Queue; len(queue) > 0 {
|
|
||||||
opts = append(opts, broker.SubscribeGroup(queue))
|
|
||||||
}
|
|
||||||
|
|
||||||
subCtx := config.Context
|
|
||||||
if cx := sb.Options().Context; cx != nil {
|
|
||||||
subCtx = cx
|
|
||||||
}
|
|
||||||
opts = append(opts, broker.SubscribeContext(subCtx))
|
|
||||||
opts = append(opts, broker.SubscribeAutoAck(sb.Options().AutoAck))
|
|
||||||
|
|
||||||
if config.Logger.V(logger.InfoLevel) {
|
|
||||||
config.Logger.Infof(config.Context, "Subscribing to topic: %s", sb.Topic())
|
|
||||||
}
|
|
||||||
sub, err := config.Broker.Subscribe(subCtx, sb.Topic(), handler, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
g.subscribers[sb] = []broker.Subscriber{sub}
|
|
||||||
}
|
|
||||||
|
|
||||||
g.registered = true
|
g.registered = true
|
||||||
g.rsvc = service
|
g.rsvc = service
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) Deregister() error {
|
func (g *Server) Deregister() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
g.RLock()
|
g.RLock()
|
||||||
@@ -782,7 +766,7 @@ func (g *grpcServer) Deregister() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) Start() error {
|
func (g *Server) Start() error {
|
||||||
g.RLock()
|
g.RLock()
|
||||||
if g.started {
|
if g.started {
|
||||||
g.RUnlock()
|
g.RUnlock()
|
||||||
@@ -792,10 +776,6 @@ func (g *grpcServer) Start() error {
|
|||||||
|
|
||||||
config := g.Options()
|
config := g.Options()
|
||||||
|
|
||||||
for _, k := range config.Codecs {
|
|
||||||
encoding.RegisterCodec(&wrapMicroCodec{k})
|
|
||||||
}
|
|
||||||
|
|
||||||
// micro: config.Transport.Listen(config.Address)
|
// micro: config.Transport.Listen(config.Address)
|
||||||
var ts net.Listener
|
var ts net.Listener
|
||||||
var err error
|
var err error
|
||||||
@@ -859,6 +839,10 @@ func (g *grpcServer) Start() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = g.subscribe(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// micro: go ts.Accept(s.accept)
|
// micro: go ts.Accept(s.accept)
|
||||||
go func() {
|
go func() {
|
||||||
if err = g.srv.Serve(ts); err != nil {
|
if err = g.srv.Serve(ts); err != nil {
|
||||||
@@ -970,7 +954,38 @@ func (g *grpcServer) Start() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) Stop() error {
|
func (g *Server) subscribe() error {
|
||||||
|
config := g.opts
|
||||||
|
|
||||||
|
for sb := range g.subscribers {
|
||||||
|
handler := g.createSubHandler(sb, config)
|
||||||
|
var opts []broker.SubscribeOption
|
||||||
|
if queue := sb.Options().Queue; len(queue) > 0 {
|
||||||
|
opts = append(opts, broker.SubscribeGroup(queue))
|
||||||
|
}
|
||||||
|
|
||||||
|
subCtx := config.Context
|
||||||
|
if cx := sb.Options().Context; cx != nil {
|
||||||
|
subCtx = cx
|
||||||
|
}
|
||||||
|
opts = append(opts, broker.SubscribeContext(subCtx))
|
||||||
|
opts = append(opts, broker.SubscribeAutoAck(sb.Options().AutoAck))
|
||||||
|
opts = append(opts, broker.SubscribeBodyOnly(sb.Options().BodyOnly))
|
||||||
|
|
||||||
|
if config.Logger.V(logger.InfoLevel) {
|
||||||
|
config.Logger.Infof(config.Context, "Subscribing to topic: %s", sb.Topic())
|
||||||
|
}
|
||||||
|
sub, err := config.Broker.Subscribe(subCtx, sb.Topic(), handler, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
g.subscribers[sb] = []broker.Subscriber{sub}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Server) Stop() error {
|
||||||
g.RLock()
|
g.RLock()
|
||||||
if !g.started {
|
if !g.started {
|
||||||
g.RUnlock()
|
g.RUnlock()
|
||||||
@@ -990,14 +1005,18 @@ func (g *grpcServer) Stop() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) String() string {
|
func (g *Server) String() string {
|
||||||
return "grpc"
|
return "grpc"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) Name() string {
|
func (g *Server) Name() string {
|
||||||
return g.opts.Name
|
return g.opts.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(opts ...server.Option) server.Server {
|
func (g *Server) GRPCServer() *grpc.Server {
|
||||||
return newGRPCServer(opts...)
|
return g.srv
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServer(opts ...server.Option) *Server {
|
||||||
|
return newServer(opts...)
|
||||||
}
|
}
|
||||||
|
17
options.go
17
options.go
@@ -9,10 +9,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
codecsKey struct{}
|
codecsKey struct{}
|
||||||
grpcOptions struct{}
|
grpcOptions struct{}
|
||||||
maxMsgSizeKey struct{}
|
maxMsgSizeKey struct{}
|
||||||
reflectionKey struct{}
|
reflectionKey struct{}
|
||||||
|
unknownServiceHandlerKey struct{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// gRPC Codec to be used to encode/decode requests for a given content type
|
// gRPC Codec to be used to encode/decode requests for a given content type
|
||||||
@@ -37,8 +38,7 @@ func Options(opts ...grpc.ServerOption) server.Option {
|
|||||||
|
|
||||||
//
|
//
|
||||||
// MaxMsgSize set the maximum message in bytes the server can receive and
|
// MaxMsgSize set the maximum message in bytes the server can receive and
|
||||||
// send. Default maximum message size is 4 MB.
|
// send. Default maximum message size is 4 MB.
|
||||||
//
|
|
||||||
func MaxMsgSize(s int) server.Option {
|
func MaxMsgSize(s int) server.Option {
|
||||||
return server.SetOption(maxMsgSizeKey{}, s)
|
return server.SetOption(maxMsgSizeKey{}, s)
|
||||||
}
|
}
|
||||||
@@ -47,3 +47,8 @@ func MaxMsgSize(s int) server.Option {
|
|||||||
func Reflection(b bool) server.Option {
|
func Reflection(b bool) server.Option {
|
||||||
return server.SetOption(reflectionKey{}, b)
|
return server.SetOption(reflectionKey{}, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnknownServiceHandler enables support for all services
|
||||||
|
func UnknownServiceHandler(h grpc.StreamHandler) server.Option {
|
||||||
|
return server.SetOption(unknownServiceHandlerKey{}, h)
|
||||||
|
}
|
||||||
|
@@ -31,7 +31,6 @@ type rpcMessage struct {
|
|||||||
header metadata.Metadata
|
header metadata.Metadata
|
||||||
topic string
|
topic string
|
||||||
contentType string
|
contentType string
|
||||||
body []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rpcRequest) ContentType() string {
|
func (r *rpcRequest) ContentType() string {
|
||||||
|
@@ -102,7 +102,7 @@ func newSubscriber(topic string, sub interface{}, opts ...server.SubscriberOptio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grpcServer) createSubHandler(sb *subscriber, opts server.Options) broker.Handler {
|
func (g *Server) createSubHandler(sb *subscriber, opts server.Options) broker.Handler {
|
||||||
return func(p broker.Event) (err error) {
|
return func(p broker.Event) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
|
Reference in New Issue
Block a user