use own fork

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2020-09-20 16:08:45 +03:00
parent 4c65c013e5
commit 2c03ee8ec6
33 changed files with 1844 additions and 892 deletions

24
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,24 @@
---
name: Bug report
about: For reporting bugs in go-micro
title: "[BUG]"
labels: ''
assignees: ''
---
**Describe the bug**
1. What are you trying to do?
2. What did you expect to happen?
3. What happens instead?
**How to reproduce the bug:**
If possible, please include a minimal code snippet here.
**Environment:**
Go Version: please paste `go version` output here
```
please paste `go env` output here
```

View File

@ -0,0 +1,17 @@
---
name: Feature request / Enhancement
about: If you have a need not served by go-micro
title: "[FEATURE]"
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Additional context**
Add any other context or screenshots about the feature request here.

14
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@ -0,0 +1,14 @@
---
name: Question
about: Ask a question about go-micro
title: ''
labels: ''
assignees: ''
---
Before asking, please check if your question has already been answered:
1. Check the documentation - https://micro.mu/docs/
2. Check the examples and plugins - https://github.com/micro/examples & https://github.com/micro/go-plugins
3. Search existing issues

9
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,9 @@
## Pull Request template
Please, go through these steps before clicking submit on this PR.
1. Give a descriptive title to your PR.
2. Provide a description of your changes.
3. Make sure you have some relevant tests.
4. Put `closes #XXXX` in your comment to auto-close the issue that your PR fixes (if applicable).
**PLEASE REMOVE THIS TEMPLATE BEFORE SUBMITTING**

13
.github/stale.sh vendored Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash -ex
export PATH=$PATH:$(pwd)/bin
export GO111MODULE=on
export GOBIN=$(pwd)/bin
#go get github.com/rvflash/goup@v0.4.1
#goup -v ./...
#go get github.com/psampaz/go-mod-outdated@v0.6.0
go list -u -m -mod=mod -json all | go-mod-outdated -update -direct -ci || true
#go list -u -m -json all | go-mod-outdated -update

46
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,46 @@
name: build
on:
push:
branches:
- master
jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
- name: setup
uses: actions/setup-go@v1
with:
go-version: 1.15
- name: checkout
uses: actions/checkout@v2
- name: cache
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: deps
run: go get -v -t -d ./...
- name: test
env:
INTEGRATION_TESTS: yes
run: go test -mod readonly -v ./...
lint:
name: lint
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- name: lint
uses: golangci/golangci-lint-action@v1
continue-on-error: true
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.30
# Optional: working directory, useful for monorepos
# working-directory: somedir
# Optional: golangci-lint command line arguments.
# args: --issues-exit-code=0
# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true

46
.github/workflows/pr.yml vendored Normal file
View File

@ -0,0 +1,46 @@
name: prbuild
on:
pull_request:
branches:
- master
jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
- name: setup
uses: actions/setup-go@v1
with:
go-version: 1.15
- name: checkout
uses: actions/checkout@v2
- name: cache
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: deps
run: go get -v -t -d ./...
- name: test
env:
INTEGRATION_TESTS: yes
run: go test -mod readonly -v ./...
lint:
name: lint
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- name: lint
uses: golangci/golangci-lint-action@v1
continue-on-error: true
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.30
# Optional: working directory, useful for monorepos
# working-directory: somedir
# Optional: golangci-lint command line arguments.
# args: --issues-exit-code=0
# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true

127
codec.go
View File

@ -1,18 +1,19 @@
package grpc package grpc
import ( import (
b "bytes"
"encoding/json" "encoding/json"
"strings" "strings"
b "bytes" oldjsonpb "github.com/golang/protobuf/jsonpb"
oldproto "github.com/golang/protobuf/proto"
"github.com/golang/protobuf/jsonpb" bytes "github.com/unistack-org/micro-codec-bytes"
"github.com/golang/protobuf/proto" "github.com/unistack-org/micro/v3/codec"
"github.com/micro/go-micro/v3/codec"
"github.com/micro/go-micro/v3/codec/bytes"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/encoding" "google.golang.org/grpc/encoding"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
jsonpb "google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
) )
type jsonCodec struct{} type jsonCodec struct{}
@ -20,11 +21,28 @@ type bytesCodec struct{}
type protoCodec struct{} type protoCodec struct{}
type wrapCodec struct{ encoding.Codec } type wrapCodec struct{ encoding.Codec }
var jsonpbMarshaler = &jsonpb.Marshaler{ var (
EnumsAsInts: false, jsonpbMarshaler = jsonpb.MarshalOptions{
EmitDefaults: false, UseEnumNumbers: false,
EmitUnpopulated: false,
UseProtoNames: true,
AllowPartial: false,
}
jsonpbUnmarshaler = jsonpb.UnmarshalOptions{
DiscardUnknown: false,
AllowPartial: false,
}
oldjsonpbMarshaler = oldjsonpb.Marshaler{
OrigName: true, OrigName: true,
} EmitDefaults: false,
}
oldjsonpbUnmarshaler = oldjsonpb.Unmarshaler{
AllowUnknownFields: false,
}
)
var ( var (
defaultGRPCCodecs = map[string]encoding.Codec{ defaultGRPCCodecs = map[string]encoding.Codec{
@ -44,39 +62,52 @@ func (w wrapCodec) String() string {
} }
func (w wrapCodec) Marshal(v interface{}) ([]byte, error) { func (w wrapCodec) Marshal(v interface{}) ([]byte, error) {
b, ok := v.(*bytes.Frame) switch m := v.(type) {
if ok { case *bytes.Frame:
return b.Data, nil return m.Data, nil
} }
return w.Codec.Marshal(v) return w.Codec.Marshal(v)
} }
func (w wrapCodec) Unmarshal(data []byte, v interface{}) error { func (w wrapCodec) Unmarshal(data []byte, v interface{}) error {
b, ok := v.(*bytes.Frame) if len(data) == 0 {
if ok {
b.Data = data
return nil return nil
} }
if v == nil { if v == nil {
return nil return nil
} }
switch m := v.(type) {
case *bytes.Frame:
m.Data = data
return nil
}
return w.Codec.Unmarshal(data, v) return w.Codec.Unmarshal(data, v)
} }
func (protoCodec) Marshal(v interface{}) ([]byte, error) { func (protoCodec) Marshal(v interface{}) ([]byte, error) {
m, ok := v.(proto.Message) switch m := v.(type) {
if !ok { case proto.Message:
return nil, codec.ErrInvalidMessage
}
return proto.Marshal(m) return proto.Marshal(m)
case oldproto.Message:
return oldproto.Marshal(m)
}
return nil, codec.ErrInvalidMessage
} }
func (protoCodec) Unmarshal(data []byte, v interface{}) error { func (protoCodec) Unmarshal(data []byte, v interface{}) error {
m, ok := v.(proto.Message) if len(data) == 0 {
if !ok { return nil
return codec.ErrInvalidMessage
} }
if v == nil {
return nil
}
switch m := v.(type) {
case proto.Message:
return proto.Unmarshal(data, m) return proto.Unmarshal(data, m)
case oldproto.Message:
return oldproto.Unmarshal(data, m)
}
return codec.ErrInvalidMessage
} }
func (protoCodec) Name() string { func (protoCodec) Name() string {
@ -84,11 +115,14 @@ func (protoCodec) Name() string {
} }
func (jsonCodec) Marshal(v interface{}) ([]byte, error) { func (jsonCodec) Marshal(v interface{}) ([]byte, error) {
if pb, ok := v.(proto.Message); ok { switch m := v.(type) {
s, err := jsonpbMarshaler.MarshalToString(pb) case proto.Message:
return []byte(s), err return jsonpbMarshaler.Marshal(m)
case oldproto.Message:
buf := b.NewBuffer(nil)
err := oldjsonpbMarshaler.Marshal(buf, m)
return buf.Bytes(), err
} }
return json.Marshal(v) return json.Marshal(v)
} }
@ -96,8 +130,14 @@ func (jsonCodec) Unmarshal(data []byte, v interface{}) error {
if len(data) == 0 { if len(data) == 0 {
return nil return nil
} }
if pb, ok := v.(proto.Message); ok { if v == nil {
return jsonpb.Unmarshal(b.NewReader(data), pb) return nil
}
switch m := v.(type) {
case proto.Message:
return jsonpbUnmarshaler.Unmarshal(data, m)
case oldproto.Message:
return oldjsonpbUnmarshaler.Unmarshal(b.NewReader(data), m)
} }
return json.Unmarshal(data, v) return json.Unmarshal(data, v)
} }
@ -107,20 +147,26 @@ func (jsonCodec) Name() string {
} }
func (bytesCodec) Marshal(v interface{}) ([]byte, error) { func (bytesCodec) Marshal(v interface{}) ([]byte, error) {
b, ok := v.(*[]byte) switch m := v.(type) {
if !ok { case *[]byte:
return nil, codec.ErrInvalidMessage return *m, nil
} }
return *b, nil return nil, codec.ErrInvalidMessage
} }
func (bytesCodec) Unmarshal(data []byte, v interface{}) error { func (bytesCodec) Unmarshal(data []byte, v interface{}) error {
b, ok := v.(*[]byte) if len(data) == 0 {
if !ok {
return codec.ErrInvalidMessage
}
*b = data
return nil return nil
}
if v == nil {
return nil
}
switch m := v.(type) {
case *[]byte:
*m = data
return nil
}
return codec.ErrInvalidMessage
} }
func (bytesCodec) Name() string { func (bytesCodec) Name() string {
@ -158,8 +204,9 @@ func (g *grpcCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error {
func (g *grpcCodec) ReadBody(v interface{}) error { func (g *grpcCodec) ReadBody(v interface{}) error {
// caller has requested a frame // caller has requested a frame
if f, ok := v.(*bytes.Frame); ok { switch m := v.(type) {
return g.ServerStream.RecvMsg(f) case *bytes.Frame:
return g.ServerStream.RecvMsg(m)
} }
return g.ServerStream.RecvMsg(v) return g.ServerStream.RecvMsg(v)
} }

View File

@ -3,7 +3,7 @@ package grpc
import ( import (
"context" "context"
"github.com/micro/go-micro/v3/server" "github.com/unistack-org/micro/v3/server"
) )
func setServerOption(k, v interface{}) server.Option { func setServerOption(k, v interface{}) server.Option {

View File

@ -1,13 +1,18 @@
package grpc package grpc
import ( import (
"context"
"io"
"net/http" "net/http"
"os"
"github.com/micro/go-micro/v3/errors" pb "github.com/unistack-org/micro-server-grpc/errors"
"github.com/unistack-org/micro/v3/errors"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
) )
var errMapping = map[int32]codes.Code{ var (
errMapping = map[int32]codes.Code{
http.StatusOK: codes.OK, http.StatusOK: codes.OK,
http.StatusBadRequest: codes.InvalidArgument, http.StatusBadRequest: codes.InvalidArgument,
http.StatusRequestTimeout: codes.DeadlineExceeded, http.StatusRequestTimeout: codes.DeadlineExceeded,
@ -19,15 +24,66 @@ var errMapping = map[int32]codes.Code{
http.StatusNotImplemented: codes.Unimplemented, http.StatusNotImplemented: codes.Unimplemented,
http.StatusInternalServerError: codes.Internal, http.StatusInternalServerError: codes.Internal,
http.StatusServiceUnavailable: codes.Unavailable, http.StatusServiceUnavailable: codes.Unavailable,
}
)
// convertCode converts a standard Go error into its canonical code. Note that
// this is only used to translate the error returned by the server applications.
func convertCode(err error) codes.Code {
switch err {
case nil:
return codes.OK
case io.EOF:
return codes.OutOfRange
case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF:
return codes.FailedPrecondition
case os.ErrInvalid:
return codes.InvalidArgument
case context.Canceled:
return codes.Canceled
case context.DeadlineExceeded:
return codes.DeadlineExceeded
}
switch {
case os.IsExist(err):
return codes.AlreadyExists
case os.IsNotExist(err):
return codes.NotFound
case os.IsPermission(err):
return codes.PermissionDenied
}
return codes.Unknown
} }
func microError(err *errors.Error) codes.Code { func microError(err error) codes.Code {
if err == nil { if err == nil {
return codes.OK return codes.OK
} }
if code, ok := errMapping[err.Code]; ok { var ec int32
switch verr := err.(type) {
case *errors.Error:
ec = verr.Code
case *pb.Error:
ec = verr.Code
}
if code, ok := errMapping[ec]; ok {
return code return code
} }
return codes.Unknown return codes.Unknown
} }
func pbError(err error) *pb.Error {
switch verr := err.(type) {
case nil:
return nil
case *errors.Error:
return &pb.Error{Id: verr.Id, Code: verr.Code, Detail: verr.Detail, Status: verr.Status}
case *pb.Error:
return verr
default:
return &pb.Error{Code: 500, Detail: err.Error()}
}
}

159
errors/errors.go Normal file
View File

@ -0,0 +1,159 @@
package errors
import (
"fmt"
)
func (e *Error) Error() string {
return fmt.Sprintf(`{"id":"%s","code":%d,"detail":"%s","status":"%s"}`, e.Id, e.Code, e.Detail, e.Status)
}
// New generates a custom error.
func New(id, detail string, code int32) error {
return &Error{
Id: id,
Code: code,
Detail: detail,
// Status: http.StatusText(int(code)),
}
}
// BadRequest generates a 400 error.
func BadRequest(id, format string, a ...interface{}) error {
return &Error{
Id: id,
Code: 400,
Detail: fmt.Sprintf(format, a...),
// Status: http.StatusText(400),
}
}
// Unauthorized generates a 401 error.
func Unauthorized(id, format string, a ...interface{}) error {
return &Error{
Id: id,
Code: 401,
Detail: fmt.Sprintf(format, a...),
// Status: http.StatusText(401),
}
}
// Forbidden generates a 403 error.
func Forbidden(id, format string, a ...interface{}) error {
return &Error{
Id: id,
Code: 403,
Detail: fmt.Sprintf(format, a...),
// Status: http.StatusText(403),
}
}
// NotFound generates a 404 error.
func NotFound(id, format string, a ...interface{}) error {
return &Error{
Id: id,
Code: 404,
Detail: fmt.Sprintf(format, a...),
// Status: http.StatusText(404),
}
}
// MethodNotAllowed generates a 405 error.
func MethodNotAllowed(id, format string, a ...interface{}) error {
return &Error{
Id: id,
Code: 405,
Detail: fmt.Sprintf(format, a...),
//Status: http.StatusText(405),
}
}
// Timeout generates a 408 error.
func Timeout(id, format string, a ...interface{}) error {
return &Error{
Id: id,
Code: 408,
Detail: fmt.Sprintf(format, a...),
//Status: http.StatusText(408),
}
}
// Conflict generates a 409 error.
func Conflict(id, format string, a ...interface{}) error {
return &Error{
Id: id,
Code: 409,
Detail: fmt.Sprintf(format, a...),
//Status: http.StatusText(409),
}
}
// InternalServerError generates a 500 error.
func InternalServerError(id, format string, a ...interface{}) error {
return &Error{
Id: id,
Code: 500,
Detail: fmt.Sprintf(format, a...),
//Status: http.StatusText(500),
}
}
// NotImplemented generates a 501 error
func NotImplemented(id, format string, a ...interface{}) error {
return &Error{
Id: id,
Code: 501,
Detail: fmt.Sprintf(format, a...),
//Status: http.StatusText(501),
}
}
// BadGateway generates a 502 error
func BadGateway(id, format string, a ...interface{}) error {
return &Error{
Id: id,
Code: 502,
Detail: fmt.Sprintf(format, a...),
// Status: http.StatusText(502),
}
}
// ServiceUnavailable generates a 503 error
func ServiceUnavailable(id, format string, a ...interface{}) error {
return &Error{
Id: id,
Code: 503,
Detail: fmt.Sprintf(format, a...),
//Status: http.StatusText(503),
}
}
// GatewayTimeout generates a 504 error
func GatewayTimeout(id, format string, a ...interface{}) error {
return &Error{
Id: id,
Code: 504,
Detail: fmt.Sprintf(format, a...),
//Status: http.StatusText(504),
}
}
// Equal tries to compare errors
func Equal(err1 error, err2 error) bool {
verr1, ok1 := err1.(*Error)
verr2, ok2 := err2.(*Error)
if ok1 != ok2 {
return false
}
if !ok1 {
return err1 == err2
}
if verr1.Code != verr2.Code {
return false
}
return true
}

173
errors/errors.pb.go Normal file
View File

@ -0,0 +1,173 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0-devel
// protoc v3.6.1
// source: errors.proto
package errors
import (
proto "github.com/golang/protobuf/proto"
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)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type Error struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Code int32 `protobuf:"varint,2,opt,name=code,proto3" json:"code,omitempty"`
Detail string `protobuf:"bytes,3,opt,name=detail,proto3" json:"detail,omitempty"`
Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"`
}
func (x *Error) Reset() {
*x = Error{}
if protoimpl.UnsafeEnabled {
mi := &file_errors_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Error) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Error) ProtoMessage() {}
func (x *Error) ProtoReflect() protoreflect.Message {
mi := &file_errors_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 Error.ProtoReflect.Descriptor instead.
func (*Error) Descriptor() ([]byte, []int) {
return file_errors_proto_rawDescGZIP(), []int{0}
}
func (x *Error) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *Error) GetCode() int32 {
if x != nil {
return x.Code
}
return 0
}
func (x *Error) GetDetail() string {
if x != nil {
return x.Detail
}
return ""
}
func (x *Error) GetStatus() string {
if x != nil {
return x.Status
}
return ""
}
var File_errors_proto protoreflect.FileDescriptor
var file_errors_proto_rawDesc = []byte{
0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06,
0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0x5b, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12,
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12,
0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63,
0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x73,
0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61,
0x74, 0x75, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_errors_proto_rawDescOnce sync.Once
file_errors_proto_rawDescData = file_errors_proto_rawDesc
)
func file_errors_proto_rawDescGZIP() []byte {
file_errors_proto_rawDescOnce.Do(func() {
file_errors_proto_rawDescData = protoimpl.X.CompressGZIP(file_errors_proto_rawDescData)
})
return file_errors_proto_rawDescData
}
var file_errors_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_errors_proto_goTypes = []interface{}{
(*Error)(nil), // 0: errors.Error
}
var file_errors_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
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_errors_proto_init() }
func file_errors_proto_init() {
if File_errors_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_errors_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Error); 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_errors_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_errors_proto_goTypes,
DependencyIndexes: file_errors_proto_depIdxs,
MessageInfos: file_errors_proto_msgTypes,
}.Build()
File_errors_proto = out.File
file_errors_proto_rawDesc = nil
file_errors_proto_goTypes = nil
file_errors_proto_depIdxs = nil
}

21
errors/errors.pb.micro.go Normal file
View File

@ -0,0 +1,21 @@
// Code generated by protoc-gen-micro. DO NOT EDIT.
// source: errors.proto
package errors
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package

10
errors/errors.proto Normal file
View File

@ -0,0 +1,10 @@
syntax = "proto3";
package errors;
message Error {
string id = 1;
int32 code = 2;
string detail = 3;
string status = 4;
};

View File

@ -5,7 +5,7 @@ import (
"reflect" "reflect"
"strings" "strings"
"github.com/micro/go-micro/v3/registry" "github.com/unistack-org/micro/v3/registry"
) )
func extractValue(v reflect.Type, d int) *registry.Value { func extractValue(v reflect.Type, d int) *registry.Value {

View File

@ -5,7 +5,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/micro/go-micro/v3/registry" "github.com/unistack-org/micro/v3/registry"
) )
type testHandler struct{} type testHandler struct{}

4
generate.go Normal file
View File

@ -0,0 +1,4 @@
package grpc
//go:generate protoc -I./proto -I. --go-grpc_out=paths=source_relative:./proto --go_out=paths=source_relative:./proto --micro_out=paths=source_relative:./proto proto/test.proto
//go:generate protoc -I./errors -I. --go-grpc_out=paths=source_relative:./errors --go_out=paths=source_relative:./errors --micro_out=paths=source_relative:./errors errors/errors.proto

16
go.mod Normal file
View File

@ -0,0 +1,16 @@
module github.com/unistack-org/micro-server-grpc
go 1.15
require (
github.com/golang/protobuf v1.4.2
github.com/unistack-org/micro-broker-memory v0.0.0-20200905101815-4594aa2807e9
github.com/unistack-org/micro-client-grpc v0.0.0-20200910215954-fef2610f9ce6
github.com/unistack-org/micro-codec-bytes v0.0.0-20200828083432-4e49e953d844
github.com/unistack-org/micro-registry-memory v0.0.0-20200905064113-34be66be749f
github.com/unistack-org/micro-router-registry v0.0.0-20200920130103-a1ccc75a7761
github.com/unistack-org/micro/v3 v3.0.0-gamma.0.20200920124807-9b11ea527aeb
golang.org/x/net v0.0.0-20200904194848-62affa334b73
google.golang.org/grpc v1.31.1
google.golang.org/protobuf v1.25.0
)

497
go.sum Normal file
View File

@ -0,0 +1,497 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw=
github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E=
github.com/Azure/go-autorest/autorest/adal v0.2.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E=
github.com/Azure/go-autorest/autorest/azure/auth v0.1.0/go.mod h1:Gf7/i2FUpyb/sGBLIFxTBzrNzBo7aPXXE3ZVeDRwdpM=
github.com/Azure/go-autorest/autorest/azure/cli v0.1.0/go.mod h1:Dk8CUAt/b/PzkfeRsWzVG9Yj3ps8mS8ECztu43rdU8U=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ=
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/caddyserver/certmagic v0.10.6/go.mod h1:Y8jcUBctgk/IhpAzlHKfimZNyXCkfGgRTC0orl8gROQ=
github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/ef-ds/deque v1.0.4-0.20190904040645-54cb57c252a1/go.mod h1:HvODWzv6Y6kBf3Ah2WzN1bHjDUezGLaAhwuWVwfpEJs=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch/v5 v5.0.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/evanphx/json-patch/v5 v5.1.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-acme/lego/v3 v3.4.0/go.mod h1:xYbLDuxq3Hy4bMUT1t9JIuz6GWIWb3m5X+TeTHYaT7M=
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-ini/ini v1.44.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.3/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA=
github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w=
github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA=
github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/micro/cli/v2 v2.1.2 h1:43J1lChg/rZCC1rvdqZNFSQDrGT7qfMrtp6/ztpIkEM=
github.com/micro/cli/v2 v2.1.2/go.mod h1:EguNh6DAoWKm9nmk+k/Rg0H3lQnDxqzu5x5srOtGtYg=
github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw=
github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ=
github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ=
github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3LDoToVTxDoQ=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY=
github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY=
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
github.com/unistack-org/micro-broker-memory v0.0.0-20200905101815-4594aa2807e9 h1:SHiNeIiNjs7BOjmS4tpb3amZKldUTigFiYtWzWOvHCU=
github.com/unistack-org/micro-broker-memory v0.0.0-20200905101815-4594aa2807e9/go.mod h1:j19KFne7Y8JvNXHwhjgjVJWAZDoqbnArZTMDEjyVWu0=
github.com/unistack-org/micro-client-grpc v0.0.0-20200904205035-ffbb3e990960 h1:MNiHfMdNUWKn6RrFFphYPKjpTCBSH4vGjCglZeUW9Tg=
github.com/unistack-org/micro-client-grpc v0.0.0-20200904205035-ffbb3e990960/go.mod h1:we/JUfnT+yZYvZGtMCksPtqGAqqmwUChmrOmAvSf8bE=
github.com/unistack-org/micro-client-grpc v0.0.0-20200910215954-fef2610f9ce6 h1:+YjhltzGWFVDEJWypkbl60CcVGUuiagOTiQAOl5kqXM=
github.com/unistack-org/micro-client-grpc v0.0.0-20200910215954-fef2610f9ce6/go.mod h1:YDH2dZp7ZeHNvJYDgKEJU67G7tu9+hf701rODFfm5D4=
github.com/unistack-org/micro-codec-bytes v0.0.0-20200827104921-3616a69473a6/go.mod h1:g5sOI8TWgGZiVHe8zoUPdtz7+0oLnqTnfBoai6Qb7jE=
github.com/unistack-org/micro-codec-bytes v0.0.0-20200828083432-4e49e953d844 h1:5b1yuSllbsMm/9fUIlIXSr8DbsKT/sAKSCgOx6+SAfI=
github.com/unistack-org/micro-codec-bytes v0.0.0-20200828083432-4e49e953d844/go.mod h1:g5sOI8TWgGZiVHe8zoUPdtz7+0oLnqTnfBoai6Qb7jE=
github.com/unistack-org/micro-config-cmd v0.0.0-20200828075439-d859b9d7265b h1:v5Ak+Sr780jZclFDnx82g5biF0N5HRVKphEpJhbnVUs=
github.com/unistack-org/micro-config-cmd v0.0.0-20200828075439-d859b9d7265b/go.mod h1:6pm1cadbwsFcEW1ZbV5Fp0i3goR3TNfROMNSPih3I8k=
github.com/unistack-org/micro-config-cmd v0.0.0-20200909210346-ec89783dc46c/go.mod h1:6pm1cadbwsFcEW1ZbV5Fp0i3goR3TNfROMNSPih3I8k=
github.com/unistack-org/micro-config-cmd v0.0.0-20200909210755-6e7e85eeab34 h1:VHc98t4SoiCF/jbkFu2e/j+IyJ/+MFQ1T+INNL7LubU=
github.com/unistack-org/micro-config-cmd v0.0.0-20200909210755-6e7e85eeab34/go.mod h1:fT1gYn+TtfVZZ5tNx56bZIncJjmlji66g7GKdWua5hE=
github.com/unistack-org/micro-registry-memory v0.0.0-20200827091533-c21be2366d55/go.mod h1:F80jL0sIkViezC5CpvJQ4q2+Zzu4fI8zhgyZ+tJdD9o=
github.com/unistack-org/micro-registry-memory v0.0.0-20200905064113-34be66be749f h1:aJwqchNCtEYpwCi/Y5MDhQuc1d8RQ5CX7ZgdmFhYeIY=
github.com/unistack-org/micro-registry-memory v0.0.0-20200905064113-34be66be749f/go.mod h1:eqAeQoWZMLVScoXEurBfkI5I96Gl1MCN2A/cX1JqaOY=
github.com/unistack-org/micro-router-registry v0.0.0-20200828092752-19e0b3a7210f h1:Z76C488sBUdjKLZSNHVqrTpdtkg78GJaiogJFY2mSYA=
github.com/unistack-org/micro-router-registry v0.0.0-20200828092752-19e0b3a7210f/go.mod h1:RpBz21l+mF6rK+3iwg8/aDSmixxnymtjqfYcghSMq3w=
github.com/unistack-org/micro-router-registry v0.0.0-20200905063806-8285d1378d3c h1:3ClxxLORWg28mQGTttSO0qBrHn6BiIWCEE4ePenkHLc=
github.com/unistack-org/micro-router-registry v0.0.0-20200905063806-8285d1378d3c/go.mod h1:p7nD3hq95yfpAYanDRdehcuRxpgFrM28tpeu8DBfygU=
github.com/unistack-org/micro-router-registry v0.0.0-20200920130103-a1ccc75a7761 h1:ojJXjWNqSXF6LGkiOKpDp+Cq5pfGcu1EmTBPbyWTYZg=
github.com/unistack-org/micro-router-registry v0.0.0-20200920130103-a1ccc75a7761/go.mod h1:mobzF4hd2yI5aZcxdE2Q5bUAGA+g0mV6o/k228berxY=
github.com/unistack-org/micro-server-grpc v0.0.0-20200831094349-1205641fc084/go.mod h1:Ky7H+xcszJ//4Z6Tl1Q9iPW+Qy1M+7qPW6ZK4mXayZU=
github.com/unistack-org/micro-server-grpc v0.0.0-20200907110628-32734086c27f/go.mod h1:IX1U33kvgx7wgV3avEjHUi8UALCZsveNLbLnZbxMFp4=
github.com/unistack-org/micro/v3 v3.0.0-20200827081802-b4ccde222831/go.mod h1:rPQbnry3nboAnMczj8B1Gzlcyv/HYoMZLgd3/3nttJ4=
github.com/unistack-org/micro/v3 v3.0.0-20200827083227-aa99378adc6e/go.mod h1:rPQbnry3nboAnMczj8B1Gzlcyv/HYoMZLgd3/3nttJ4=
github.com/unistack-org/micro/v3 v3.0.0-20200828085518-2c136b005edd/go.mod h1:fMA60jjS3INPT4AwYm2+jTHVuWEkVYvaO/7wgEpylTk=
github.com/unistack-org/micro/v3 v3.0.0-20200831085130-7c115823a7ab/go.mod h1:iEtpu3wTYCRs3pQ3VsFEO7JBO4lOMpkOwMyrpZyIDPo=
github.com/unistack-org/micro/v3 v3.0.0-gamma.0.20200904234316-e7d418183b62/go.mod h1:mB0h+i3Sa4jD8G2dv97cAAdyh01hVQWKw4xSdmTpyOo=
github.com/unistack-org/micro/v3 v3.0.0-gamma.0.20200909210629-caec730248b1/go.mod h1:mmqHR9WelHUXqg2mELjsQ+FJHcWs6mNmXg+wEYO2T3c=
github.com/unistack-org/micro/v3 v3.0.0-gamma.0.20200920124807-9b11ea527aeb h1:ETCShJ27nTE7kMQgaf7S6p1Tbfr2tdGO6MYxZ2LTMWY=
github.com/unistack-org/micro/v3 v3.0.0-gamma.0.20200920124807-9b11ea527aeb/go.mod h1:HUzMG4Mcy97958VxWTg8zuazZgwQ/aoLZ8wtBVONwRE=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y=
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191027093000-83d349e8ac1a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d h1:92D1fum1bJLKSdr11OJ+54YeCMCGYIygTA7R/YZxH5M=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ns1/ns1-go.v2 v2.0.0-20190730140822-b51389932cbc/go.mod h1:VV+3haRsgDiVLxyifmMBrBIuCWFBPYKbRssXB9z67Hw=
gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

342
grpc.go
View File

@ -14,27 +14,28 @@ import (
"sync" "sync"
"time" "time"
"github.com/golang/protobuf/proto" oldproto "github.com/golang/protobuf/proto"
"github.com/micro/go-micro/v3/broker" pberr "github.com/unistack-org/micro-server-grpc/errors"
"github.com/micro/go-micro/v3/errors" "github.com/unistack-org/micro/v3/broker"
pberr "github.com/micro/go-micro/v3/errors/proto" "github.com/unistack-org/micro/v3/errors"
"github.com/micro/go-micro/v3/logger" "github.com/unistack-org/micro/v3/logger"
meta "github.com/micro/go-micro/v3/metadata" meta "github.com/unistack-org/micro/v3/metadata"
"github.com/micro/go-micro/v3/registry" "github.com/unistack-org/micro/v3/registry"
"github.com/micro/go-micro/v3/server" "github.com/unistack-org/micro/v3/server"
"github.com/micro/go-micro/v3/util/addr" "github.com/unistack-org/micro/v3/util/addr"
"github.com/micro/go-micro/v3/util/backoff" "github.com/unistack-org/micro/v3/util/backoff"
mgrpc "github.com/micro/go-micro/v3/util/grpc" mgrpc "github.com/unistack-org/micro/v3/util/grpc"
mnet "github.com/micro/go-micro/v3/util/net" mnet "github.com/unistack-org/micro/v3/util/net"
"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/credentials"
"google.golang.org/grpc/encoding" "google.golang.org/grpc/encoding"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer" "google.golang.org/grpc/peer"
grpcreflect "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
) )
var ( var (
@ -47,6 +48,11 @@ const (
defaultContentType = "application/grpc" defaultContentType = "application/grpc"
) )
type grpcServerReflection struct {
srv *grpc.Server
s *serverReflectionServer
}
type grpcServer struct { type grpcServer struct {
rpc *rServer rpc *rServer
srv *grpc.Server srv *grpc.Server
@ -62,8 +68,11 @@ type grpcServer struct {
// used for first registration // used for first registration
registered bool registered bool
reflection bool
// registry service instance // registry service instance
rsvc *registry.Service rsvc *registry.Service
codecs map[string]encoding.Codec
} }
func init() { func init() {
@ -73,24 +82,22 @@ func init() {
} }
func newGRPCServer(opts ...server.Option) server.Server { func newGRPCServer(opts ...server.Option) server.Server {
options := newOptions(opts...)
// create a grpc server // create a grpc server
srv := &grpcServer{ g := &grpcServer{
opts: options, opts: server.NewOptions(),
rpc: &rServer{ rpc: &rServer{
serviceMap: make(map[string]*service), serviceMap: make(map[string]*service),
}, },
handlers: make(map[string]server.Handler), handlers: make(map[string]server.Handler),
subscribers: make(map[*subscriber][]broker.Subscriber), subscribers: make(map[*subscriber][]broker.Subscriber),
exit: make(chan chan error), exit: make(chan chan error),
wg: wait(options.Context),
} }
// configure the grpc server for _, o := range opts {
srv.configure() o(&g.opts)
}
return srv return g
} }
type grpcRouter struct { type grpcRouter struct {
@ -106,20 +113,44 @@ func (r grpcRouter) ServeRequest(ctx context.Context, req server.Request, rsp se
return r.h(ctx, req, rsp) return r.h(ctx, req, rsp)
} }
func (g *grpcServer) configure(opts ...server.Option) { func (g *grpcServer) configure(opts ...server.Option) error {
g.Lock() g.Lock()
defer g.Unlock() defer g.Unlock()
// Don't reprocess where there's no config // Don't reprocess if server created
if len(opts) == 0 && g.srv != nil { if g.srv != nil {
return return nil
} }
for _, o := range opts { for _, o := range opts {
o(&g.opts) o(&g.opts)
} }
g.wg = wait(g.opts.Context) if g.opts.Registry == nil {
return fmt.Errorf("registry not set")
}
if g.opts.Broker == nil {
return fmt.Errorf("broker not set")
}
g.wg = g.opts.Wait
g.codecs = make(map[string]encoding.Codec, len(defaultGRPCCodecs))
for k, v := range defaultGRPCCodecs {
g.codecs[k] = v
}
var codecs map[string]encoding.Codec
if g.opts.Context != nil {
if v, ok := g.opts.Context.Value(codecsKey{}).(map[string]encoding.Codec); ok && v != nil {
codecs = v
}
}
for k, v := range codecs {
g.codecs[k] = v
}
maxMsgSize := g.getMaxMsgSize() maxMsgSize := g.getMaxMsgSize()
@ -139,6 +170,12 @@ func (g *grpcServer) configure(opts ...server.Option) {
g.rsvc = nil g.rsvc = nil
g.srv = grpc.NewServer(gopts...) g.srv = grpc.NewServer(gopts...)
if v, ok := g.opts.Context.Value(reflectionKey{}).(bool); ok {
g.reflection = v
}
return nil
} }
func (g *grpcServer) getMaxMsgSize() int { func (g *grpcServer) getMaxMsgSize() int {
@ -189,13 +226,13 @@ func (g *grpcServer) getListener() net.Listener {
func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) (err error) { func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) (err error) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Error("panic recovered: ", r) logger.Error("panic recovered: ", r)
logger.Error(string(debug.Stack())) logger.Error(string(debug.Stack()))
} }
err = errors.InternalServerError(g.opts.Name, "panic recovered: %v", r) err = errors.InternalServerError(g.opts.Name, "panic recovered: %v", r)
} else if err != nil { } else if err != nil {
if logger.V(logger.InfoLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Errorf("grpc handler got error: %s", err) logger.Errorf("grpc handler got error: %s", err)
} }
} }
@ -314,26 +351,41 @@ func (g *grpcServer) handler(srv interface{}, stream grpc.ServerStream) (err err
} }
// process the standard request flow // process the standard request flow
g.rpc.mu.Lock() g.rpc.mu.RLock()
service := g.rpc.serviceMap[serviceName] svc := g.rpc.serviceMap[serviceName]
g.rpc.mu.Unlock() g.rpc.mu.RUnlock()
if service == nil { if svc == nil && g.reflection && methodName == "ServerReflectionInfo" {
rfl := &grpcServerReflection{srv: g.srv, s: &serverReflectionServer{s: g.srv}}
svc = &service{}
svc.typ = reflect.TypeOf(rfl)
svc.rcvr = reflect.ValueOf(rfl)
svc.name = reflect.Indirect(svc.rcvr).Type().Name()
svc.method = make(map[string]*methodType)
typ := reflect.TypeOf(rfl)
if me, ok := typ.MethodByName("ServerReflectionInfo"); ok {
g.rpc.mu.Lock()
svc.method["ServerReflectionInfo"] = prepareEndpoint(me)
g.rpc.mu.Unlock()
}
}
if svc == nil {
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 := service.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() return status.New(codes.Unimplemented, fmt.Sprintf("unknown service %s.%s", serviceName, methodName)).Err()
} }
// process unary // process unary
if !mtype.stream { if !mtype.stream {
return g.processRequest(stream, service, mtype, ct, ctx) return g.processRequest(stream, svc, mtype, ct, ctx)
} }
// process stream // process stream
return g.processStream(stream, service, mtype, ct, ctx) return g.processStream(stream, svc, mtype, ct, ctx)
} }
func (g *grpcServer) processRequest(stream grpc.ServerStream, service *service, mtype *methodType, ct string, ctx context.Context) error { func (g *grpcServer) processRequest(stream grpc.ServerStream, service *service, mtype *methodType, ct string, ctx context.Context) error {
@ -381,7 +433,6 @@ func (g *grpcServer) processRequest(stream grpc.ServerStream, service *service,
body: b, body: b,
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), reflect.ValueOf(argv.Interface()), reflect.ValueOf(rsp)})
@ -401,32 +452,39 @@ func (g *grpcServer) processRequest(stream grpc.ServerStream, service *service,
statusCode := codes.OK statusCode := codes.OK
statusDesc := "" statusDesc := ""
// execute the handler // execute the handler
if appErr := fn(ctx, r, replyv.Interface()); appErr != nil { if appErr := fn(ctx, r, replyv.Interface()); appErr != nil {
var errStatus *status.Status var errStatus *status.Status
switch verr := appErr.(type) { switch verr := appErr.(type) {
case *errors.Error: case *pberr.Error:
perr := &pberr.Error{ perr := pbError(verr)
Id: verr.Id,
Code: verr.Code,
Detail: verr.Detail,
Status: verr.Status,
}
// micro.Error now proto based and we can attach it to grpc status
statusCode = microError(verr) statusCode = microError(verr)
statusDesc = verr.Error() statusDesc = verr.Error()
errStatus, err = status.New(statusCode, statusDesc).WithDetails(perr) errStatus, err = status.New(statusCode, statusDesc).WithDetails(perr)
if err != nil { if err != nil {
return err return err
} }
case *errors.Error:
perr := pbError(verr)
statusCode = microError(verr)
statusDesc = verr.Error()
errStatus, err = status.New(statusCode, statusDesc).WithDetails(perr)
if err != nil {
return err
}
case oldproto.Message:
// user defined error that proto based we can attach it to grpc status
statusCode = convertCode(appErr)
statusDesc = appErr.Error()
errStatus, err = status.New(statusCode, statusDesc).WithDetails(verr)
if err != nil {
return err
}
case proto.Message: case proto.Message:
// user defined error that proto based we can attach it to grpc status // user defined error that proto based we can attach it to grpc status
statusCode = convertCode(appErr) statusCode = convertCode(appErr)
statusDesc = appErr.Error() statusDesc = appErr.Error()
errStatus, err = status.New(statusCode, statusDesc).WithDetails(verr) errStatus, err = status.New(statusCode, statusDesc).WithDetails(oldproto.MessageV1(verr))
if err != nil { if err != nil {
return err return err
} }
@ -448,6 +506,48 @@ func (g *grpcServer) processRequest(stream grpc.ServerStream, service *service,
} }
} }
type reflectStream struct {
stream server.Stream
}
func (s *reflectStream) Send(rsp *grpcreflect.ServerReflectionResponse) error {
return s.stream.Send(rsp)
}
func (s *reflectStream) Recv() (*grpcreflect.ServerReflectionRequest, error) {
req := &grpcreflect.ServerReflectionRequest{}
err := s.stream.Recv(req)
return req, err
}
func (s *reflectStream) SetHeader(metadata.MD) error {
return nil
}
func (s *reflectStream) SendHeader(metadata.MD) error {
return nil
}
func (s *reflectStream) SetTrailer(metadata.MD) {
}
func (s *reflectStream) Context() context.Context {
return s.stream.Context()
}
func (s *reflectStream) SendMsg(m interface{}) error {
return s.stream.Send(m)
}
func (s *reflectStream) RecvMsg(m interface{}) error {
return s.stream.Recv(m)
}
func (g *grpcServerReflection) ServerReflectionInfo(ctx context.Context, stream server.Stream) error {
return g.s.ServerReflectionInfo(&reflectStream{stream})
}
func (g *grpcServer) processStream(stream grpc.ServerStream, service *service, mtype *methodType, ct string, ctx context.Context) error { func (g *grpcServer) processStream(stream grpc.ServerStream, service *service, mtype *methodType, ct string, ctx context.Context) error {
opts := g.opts opts := g.opts
@ -487,25 +587,35 @@ func (g *grpcServer) processStream(stream grpc.ServerStream, service *service, m
var err error var err error
var errStatus *status.Status var errStatus *status.Status
switch verr := appErr.(type) { switch verr := appErr.(type) {
case *errors.Error: case *pberr.Error:
perr := &pberr.Error{ perr := pbError(verr)
Id: verr.Id,
Code: verr.Code,
Detail: verr.Detail,
Status: verr.Status,
}
// micro.Error now proto based and we can attach it to grpc status
statusCode = microError(verr) statusCode = microError(verr)
statusDesc = verr.Error() statusDesc = verr.Error()
errStatus, err = status.New(statusCode, statusDesc).WithDetails(perr) errStatus, err = status.New(statusCode, statusDesc).WithDetails(perr)
if err != nil { if err != nil {
return err return err
} }
case *errors.Error:
perr := pbError(verr)
statusCode = microError(verr)
statusDesc = verr.Error()
errStatus, err = status.New(statusCode, statusDesc).WithDetails(perr)
if err != nil {
return err
}
case oldproto.Message:
// user defined error that proto based we can attach it to grpc status
statusCode = convertCode(appErr)
statusDesc = appErr.Error()
errStatus, err = status.New(statusCode, statusDesc).WithDetails(verr)
if err != nil {
return err
}
case proto.Message: case proto.Message:
// user defined error that proto based we can attach it to grpc status // user defined error that proto based we can attach it to grpc status
statusCode = convertCode(appErr) statusCode = convertCode(appErr)
statusDesc = appErr.Error() statusDesc = appErr.Error()
errStatus, err = status.New(statusCode, statusDesc).WithDetails(verr) errStatus, err = status.New(statusCode, statusDesc).WithDetails(oldproto.MessageV1(verr))
if err != nil { if err != nil {
return err return err
} }
@ -523,18 +633,13 @@ func (g *grpcServer) processStream(stream grpc.ServerStream, service *service, m
} }
func (g *grpcServer) newGRPCCodec(contentType string) (encoding.Codec, error) { func (g *grpcServer) newGRPCCodec(contentType string) (encoding.Codec, error) {
codecs := make(map[string]encoding.Codec) g.RLock()
if g.opts.Context != nil { defer g.RUnlock()
if v, ok := g.opts.Context.Value(codecsKey{}).(map[string]encoding.Codec); ok && v != nil {
codecs = v if c, ok := g.codecs[contentType]; ok {
}
}
if c, ok := codecs[contentType]; ok {
return c, nil
}
if c, ok := defaultGRPCCodecs[contentType]; ok {
return c, nil return c, nil
} }
return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType)
} }
@ -547,8 +652,7 @@ func (g *grpcServer) Options() server.Options {
} }
func (g *grpcServer) Init(opts ...server.Option) error { func (g *grpcServer) Init(opts ...server.Option) error {
g.configure(opts...) return g.configure(opts...)
return nil
} }
func (g *grpcServer) NewHandler(h interface{}, opts ...server.HandlerOption) server.Handler { func (g *grpcServer) NewHandler(h interface{}, opts ...server.HandlerOption) server.Handler {
@ -598,11 +702,6 @@ func (g *grpcServer) Register() error {
config := g.opts config := g.opts
g.RUnlock() g.RUnlock()
// only register if it exists or is not noop
if config.Registry == nil || config.Registry.String() == "noop" {
return nil
}
regFunc := func(service *registry.Service) error { regFunc := func(service *registry.Service) error {
var regErr error var regErr error
@ -641,14 +740,7 @@ func (g *grpcServer) Register() error {
var advt, host, port string var advt, host, port string
var cacheService bool var cacheService bool
// check the advertise address first
// if it exists then use it, otherwise
// use the address
if len(config.Advertise) > 0 {
advt = config.Advertise advt = config.Advertise
} else {
advt = config.Address
}
if cnt := strings.Count(advt, ":"); cnt >= 1 { if cnt := strings.Count(advt, ":"); cnt >= 1 {
// ipv6 address in format [host]:port or ipv4 host:port // ipv6 address in format [host]:port or ipv4 host:port
@ -679,6 +771,10 @@ func (g *grpcServer) Register() error {
Metadata: md, Metadata: md,
} }
if node.Metadata == nil {
node.Metadata = make(map[string]string, 5)
}
node.Metadata["broker"] = config.Broker.String() node.Metadata["broker"] = config.Broker.String()
node.Metadata["registry"] = config.Registry.String() node.Metadata["registry"] = config.Registry.String()
node.Metadata["server"] = g.String() node.Metadata["server"] = g.String()
@ -694,6 +790,7 @@ func (g *grpcServer) Register() error {
handlerList = append(handlerList, n) handlerList = append(handlerList, n)
} }
} }
sort.Strings(handlerList) sort.Strings(handlerList)
var subscriberList []*subscriber var subscriberList []*subscriber
@ -728,7 +825,7 @@ func (g *grpcServer) Register() error {
g.RUnlock() g.RUnlock()
if !registered { if !registered {
if logger.V(logger.InfoLevel, logger.DefaultLogger) { if logger.V(logger.InfoLevel) {
logger.Infof("Registry [%s] Registering node: %s", config.Registry.String(), node.Id) logger.Infof("Registry [%s] Registering node: %s", config.Registry.String(), node.Id)
} }
} }
@ -750,14 +847,16 @@ func (g *grpcServer) Register() error {
handler := g.createSubHandler(sb, g.opts) handler := g.createSubHandler(sb, g.opts)
var opts []broker.SubscribeOption var opts []broker.SubscribeOption
if queue := sb.Options().Queue; len(queue) > 0 { if queue := sb.Options().Queue; len(queue) > 0 {
opts = append(opts, broker.Queue(queue)) opts = append(opts, broker.SubscribeGroup(queue))
} }
if cx := sb.Options().Context; cx != nil { if cx := sb.Options().Context; cx != nil {
opts = append(opts, broker.SubscribeContext(cx)) opts = append(opts, broker.SubscribeContext(cx))
} }
if logger.V(logger.InfoLevel, logger.DefaultLogger) { opts = append(opts, broker.SubscribeAutoAck(sb.Options().AutoAck))
if logger.V(logger.InfoLevel) {
logger.Infof("Subscribing to topic: %s", sb.Topic()) logger.Infof("Subscribing to topic: %s", sb.Topic())
} }
sub, err := config.Broker.Subscribe(sb.Topic(), handler, opts...) sub, err := config.Broker.Subscribe(sb.Topic(), handler, opts...)
@ -783,11 +882,6 @@ func (g *grpcServer) Deregister() error {
config := g.opts config := g.opts
g.RUnlock() g.RUnlock()
// only register if it exists or is not noop
if config.Registry == nil || config.Registry.String() == "noop" {
return nil
}
// check the advertise address first // check the advertise address first
// if it exists then use it, otherwise // if it exists then use it, otherwise
// use the address // use the address
@ -823,7 +917,7 @@ func (g *grpcServer) Deregister() error {
Nodes: []*registry.Node{node}, Nodes: []*registry.Node{node},
} }
if logger.V(logger.InfoLevel, logger.DefaultLogger) { if logger.V(logger.InfoLevel) {
logger.Infof("Deregistering node: %s", node.Id) logger.Infof("Deregistering node: %s", node.Id)
} }
@ -848,10 +942,14 @@ func (g *grpcServer) Deregister() error {
wg.Add(1) wg.Add(1)
go func(s broker.Subscriber) { go func(s broker.Subscriber) {
defer wg.Done() defer wg.Done()
if logger.V(logger.InfoLevel, logger.DefaultLogger) { if logger.V(logger.InfoLevel) {
logger.Infof("Unsubscribing from topic: %s", s.Topic()) logger.Infof("Unsubscribing from topic: %s", s.Topic())
} }
s.Unsubscribe() if err := s.Unsubscribe(); err != nil {
if logger.V(logger.ErrorLevel) {
logger.Errorf("Unsubscribing from topic: %s err: %v", s.Topic(), err)
}
}
}(sub) }(sub)
} }
g.subscribers[sb] = nil g.subscribers[sb] = nil
@ -898,41 +996,56 @@ func (g *grpcServer) Start() error {
} }
} }
if logger.V(logger.InfoLevel, logger.DefaultLogger) { if logger.V(logger.InfoLevel) {
logger.Infof("Server [grpc] Listening on %s", ts.Addr().String()) logger.Infof("Server [grpc] Listening on %s", ts.Addr().String())
} }
g.Lock() g.Lock()
g.opts.Address = ts.Addr().String() g.opts.Address = ts.Addr().String()
if len(g.opts.Advertise) == 0 {
g.opts.Advertise = ts.Addr().String()
}
g.Unlock() g.Unlock()
// only connect if we're subscribed // only connect if we're subscribed
if len(g.subscribers) > 0 { if len(g.subscribers) > 0 {
// connect to the broker // connect to the broker
if err := config.Broker.Connect(); err != nil { if err := config.Broker.Connect(); err != nil {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Errorf("Broker [%s] connect error: %v", config.Broker.String(), err) logger.Errorf("Broker [%s] connect error: %v", config.Broker.String(), err)
} }
return err return err
} }
if logger.V(logger.InfoLevel, logger.DefaultLogger) { if logger.V(logger.InfoLevel) {
logger.Infof("Broker [%s] Connected to %s", config.Broker.String(), config.Broker.Address()) logger.Infof("Broker [%s] Connected to %s", config.Broker.String(), config.Broker.Address())
} }
} }
// use RegisterCheck func before register
if err := g.opts.RegisterCheck(g.opts.Context); err != nil {
if logger.V(logger.ErrorLevel) {
logger.Errorf("Server %s-%s register check error: %s", config.Name, config.Id, err)
}
} else {
// announce self to the world // announce self to the world
if err := g.Register(); err != nil { if err := g.Register(); err != nil {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Errorf("Server register error: %v", err) logger.Errorf("Server register error: %v", 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 {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Errorf("gRPC Server start error: %v", err) logger.Errorf("gRPC Server start error: %v", err)
} }
if err := g.Stop(); err != nil {
if logger.V(logger.ErrorLevel) {
logger.Errorf("gRPC Server stop error: %v", err)
}
}
} }
}() }()
@ -953,9 +1066,29 @@ func (g *grpcServer) Start() error {
select { select {
// register self on interval // register self on interval
case <-t.C: case <-t.C:
g.RLock()
registered := g.registered
g.RUnlock()
rerr := g.opts.RegisterCheck(g.opts.Context)
if rerr != nil && registered {
if logger.V(logger.ErrorLevel) {
logger.Errorf("Server %s-%s register check error: %s, deregister it", config.Name, config.Id, rerr)
}
// deregister self in case of error
if err := g.Deregister(); err != nil {
if logger.V(logger.ErrorLevel) {
logger.Errorf("Server %s-%s deregister error: %s", config.Name, config.Id, err)
}
}
} else if rerr != nil && !registered {
if logger.V(logger.ErrorLevel) {
logger.Errorf("Server %s-%s register check error: %s", config.Name, config.Id, rerr)
}
continue
}
if err := g.Register(); err != nil { if err := g.Register(); err != nil {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Error("Server register error: ", err) logger.Errorf("Server %s-%s register error: %s", config.Name, config.Id, err)
} }
} }
// wait for exit // wait for exit
@ -966,7 +1099,7 @@ func (g *grpcServer) Start() error {
// deregister self // deregister self
if err := g.Deregister(); err != nil { if err := g.Deregister(); err != nil {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Error("Server deregister error: ", err) logger.Error("Server deregister error: ", err)
} }
} }
@ -993,12 +1126,12 @@ func (g *grpcServer) Start() error {
// close transport // close transport
ch <- nil ch <- nil
if logger.V(logger.InfoLevel, logger.DefaultLogger) { if logger.V(logger.InfoLevel) {
logger.Infof("Broker [%s] Disconnected from %s", config.Broker.String(), config.Broker.Address()) logger.Infof("Broker [%s] Disconnected from %s", config.Broker.String(), config.Broker.Address())
} }
// disconnect broker // disconnect broker
if err := config.Broker.Disconnect(); err != nil { if err := config.Broker.Disconnect(); err != nil {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Errorf("Broker [%s] disconnect error: %v", config.Broker.String(), err) logger.Errorf("Broker [%s] disconnect error: %v", config.Broker.String(), err)
} }
} }
@ -1023,14 +1156,11 @@ func (g *grpcServer) Stop() error {
ch := make(chan error) ch := make(chan error)
g.exit <- ch g.exit <- ch
var err error err := <-ch
select {
case err = <-ch:
g.Lock() g.Lock()
g.rsvc = nil g.rsvc = nil
g.started = false g.started = false
g.Unlock() g.Unlock()
}
return err return err
} }

View File

@ -2,183 +2,94 @@ package grpc_test
import ( import (
"context" "context"
"fmt"
"testing" "testing"
bmemory "github.com/micro/go-micro/v3/broker/memory" bmemory "github.com/unistack-org/micro-broker-memory"
"github.com/micro/go-micro/v3/client" gclient "github.com/unistack-org/micro-client-grpc"
gcli "github.com/micro/go-micro/v3/client/grpc" rmemory "github.com/unistack-org/micro-registry-memory"
"github.com/micro/go-micro/v3/errors" regRouter "github.com/unistack-org/micro-router-registry"
pberr "github.com/micro/go-micro/v3/errors/proto" gserver "github.com/unistack-org/micro-server-grpc"
tgrpc "github.com/micro/go-micro/v3/network/transport/grpc" pberr "github.com/unistack-org/micro-server-grpc/errors"
rmemory "github.com/micro/go-micro/v3/registry/memory" pb "github.com/unistack-org/micro-server-grpc/proto"
"github.com/micro/go-micro/v3/router" "github.com/unistack-org/micro/v3/broker"
rtreg "github.com/micro/go-micro/v3/router/registry" "github.com/unistack-org/micro/v3/client"
"github.com/micro/go-micro/v3/server" "github.com/unistack-org/micro/v3/router"
gsrv "github.com/micro/go-micro/v3/server/grpc" "github.com/unistack-org/micro/v3/server"
pb "github.com/micro/go-micro/v3/server/grpc/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/status"
) )
// server is used to implement helloworld.GreeterServer.
type testServer struct { type testServer struct {
msgCount int pb.UnimplementedTestServer
}
func (s *testServer) Handle(ctx context.Context, msg *pb.Request) error {
s.msgCount++
return nil
}
func (s *testServer) HandleError(ctx context.Context, msg *pb.Request) error {
return fmt.Errorf("fake")
}
// TestHello implements helloworld.GreeterServer
func (s *testServer) CallPcre(ctx context.Context, req *pb.Request, rsp *pb.Response) error {
if req.Name == "Error" {
return &errors.Error{Id: "1", Code: 99, Detail: "detail"}
}
rsp.Msg = "Hello " + req.Name
return nil
}
// TestHello implements helloworld.GreeterServer
func (s *testServer) CallPcreInvalid(ctx context.Context, req *pb.Request, rsp *pb.Response) error {
if req.Name == "Error" {
return &errors.Error{Id: "1", Code: 99, Detail: "detail"}
}
rsp.Msg = "Hello " + req.Name
return nil
}
// TestHello implements helloworld.GreeterServer
func (s *testServer) Call(ctx context.Context, req *pb.Request, rsp *pb.Response) error {
if req.Name == "Error" {
return &errors.Error{Id: "1", Code: 99, Detail: "detail"}
}
if req.Name == "Panic" {
// make it panic
panic("handler panic")
}
rsp.Msg = "Hello " + req.Name
return nil
} }
/* /*
func BenchmarkServer(b *testing.B) { func (g *testServer) Call(ctx context.Context, req *pb.Request, rsp *pb.Response) error {
r := rmemory.NewRegistry() if req.Name == "Error" {
br := bmemory.NewBroker() st := status.New(codes.InvalidArgument, "error request")
tr := tgrpc.NewTransport() st, err := st.WithDetails(&pberr.Error{Id: "id", Code: 99, Detail: "detail"})
s := gsrv.NewServer( if err != nil {
server.Broker(br), return err
server.Name("foo"),
server.Registry(r),
server.Transport(tr),
)
c := gcli.NewClient(
client.Registry(r),
client.Broker(br),
client.Transport(tr),
)
ctx := context.TODO()
h := &testServer{}
pb.RegisterTestHandler(s, h)
if err := s.Start(); err != nil {
b.Fatalf("failed to start: %v", err)
} }
return st.Err()
// check registration
services, err := r.GetService("foo")
if err != nil || len(services) == 0 {
b.Fatalf("failed to get service: %v # %d", err, len(services))
} }
rsp = &pb.Response{Msg: "Hello " + req.Name}
defer func() { return nil
if err := s.Stop(); err != nil {
b.Fatalf("failed to stop: %v", err)
}
}()
b.ResetTimer()
for i := 0; i < b.N; i++ {
c.Call()
}
} }
*/ */
func (g *testServer) Call(ctx context.Context, req *pb.Request, rsp *pb.Response) error {
if req.Name == "Error" {
return &pberr.Error{Id: "id", Code: 99, Detail: "detail"}
}
rsp.Msg = "Hello " + req.Name
return nil
}
func TestGRPCServer(t *testing.T) { func TestGRPCServer(t *testing.T) {
var err error
r := rmemory.NewRegistry() r := rmemory.NewRegistry()
b := bmemory.NewBroker() b := bmemory.NewBroker(broker.Registry(r))
tr := tgrpc.NewTransport() s := gserver.NewServer(server.Address(":12345"), server.Registry(r), server.Name("helloworld"), gserver.Reflection(true))
rtr := rtreg.NewRouter(router.Registry(r)) // create router
rtr := regRouter.NewRouter(router.Registry(r))
s := gsrv.NewServer(
server.Broker(b),
server.Name("foo"),
server.Registry(r),
server.Transport(tr),
)
c := gcli.NewClient(
client.Router(rtr),
client.Broker(b),
client.Transport(tr),
)
ctx := context.TODO()
h := &testServer{} h := &testServer{}
pb.RegisterTestHandler(s, h) err = pb.RegisterTestHandler(s, h)
if err != nil {
t.Fatalf("can't register handler: %v", err)
}
if err := s.Subscribe(s.NewSubscriber("test_topic", h.Handle)); err != nil { if err = s.Init(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := s.Start(); err != nil { if err = s.Start(); err != nil {
t.Fatalf("failed to start: %v", err) t.Fatal(err)
}
// check registration
services, err := r.GetService("foo")
if err != nil || len(services) == 0 {
t.Fatalf("failed to get service: %v # %d", err, len(services))
} }
defer func() { defer func() {
if err := s.Stop(); err != nil { if err = s.Stop(); err != nil {
t.Fatalf("failed to stop: %v", err) t.Fatal(err)
} }
}() }()
cnt := 4 // create client
for i := 0; i < cnt; i++ { c := gclient.NewClient(client.Router(rtr), client.Registry(r), client.Broker(b))
msg := c.NewMessage("test_topic", &pb.Request{Name: fmt.Sprintf("msg %d", i)})
if err = c.Publish(ctx, msg); err != nil {
t.Fatal(err)
}
}
if h.msgCount != cnt { testMethods := []string{
t.Fatalf("pub/sub not work, or invalid message count %d", h.msgCount) "Test.Call",
} }
cc, err := grpc.Dial(s.Options().Address, grpc.WithInsecure())
if err != nil {
t.Fatalf("failed to dial server: %v", err)
}
testMethods := []string{"/test.Test/Call", "/go.micro.test.Test/Call"}
for _, method := range testMethods { for _, method := range testMethods {
req := c.NewRequest("helloworld", method, &pb.Request{
Name: "John",
})
rsp := pb.Response{} rsp := pb.Response{}
if err := cc.Invoke(context.Background(), method, &pb.Request{Name: "John"}, &rsp); err != nil { err = c.Call(context.TODO(), req, &rsp)
t.Fatalf("error calling server: %v", err) if err != nil {
t.Fatalf("method: %s err: %v", method, err)
} }
if rsp.Msg != "Hello John" { if rsp.Msg != "Hello John" {
@ -186,118 +97,11 @@ func TestGRPCServer(t *testing.T) {
} }
} }
// Test grpc error //rsp := rpb.ServerReflectionResponse{}
rsp := pb.Response{} //req := c.NewRequest("helloworld", "Test.ServerReflectionInfo", &rpb.ServerReflectionRequest{}, client.StreamingRequest())
//if err := c.Call(context.TODO(), req, &rsp); err != nil {
// t.Fatal(err)
//}
if err := cc.Invoke(context.Background(), "/test.Test/Call", &pb.Request{Name: "Error"}, &rsp); err != nil { // select {}
st, ok := status.FromError(err)
if !ok {
t.Fatalf("invalid error received %#+v\n", err)
}
verr, ok := st.Details()[0].(*pberr.Error)
if !ok {
t.Fatalf("invalid error received %#+v\n", st.Details()[0])
}
if verr.Code != 99 && verr.Id != "1" && verr.Detail != "detail" {
t.Fatalf("invalid error received %#+v\n", verr)
}
}
}
// TestGRPCServerWithPanicWrapper test grpc server with panic wrapper
// gRPC server should not crash when wrapper crashed
func TestGRPCServerWithPanicWrapper(t *testing.T) {
r := rmemory.NewRegistry()
b := bmemory.NewBroker()
tr := tgrpc.NewTransport()
s := gsrv.NewServer(
server.Broker(b),
server.Name("foo"),
server.Registry(r),
server.Transport(tr),
server.WrapHandler(func(hf server.HandlerFunc) server.HandlerFunc {
return func(ctx context.Context, req server.Request, rsp interface{}) error {
// make it panic
panic("wrapper panic")
}
}),
)
h := &testServer{}
pb.RegisterTestHandler(s, h)
if err := s.Start(); err != nil {
t.Fatalf("failed to start: %v", err)
}
// check registration
services, err := r.GetService("foo")
if err != nil || len(services) == 0 {
t.Fatalf("failed to get service: %v # %d", err, len(services))
}
defer func() {
if err := s.Stop(); err != nil {
t.Fatalf("failed to stop: %v", err)
}
}()
cc, err := grpc.Dial(s.Options().Address, grpc.WithInsecure())
if err != nil {
t.Fatalf("failed to dial server: %v", err)
}
rsp := pb.Response{}
if err := cc.Invoke(context.Background(), "/test.Test/Call", &pb.Request{Name: "John"}, &rsp); err == nil {
t.Fatal("this must return error, as wrapper should be panic")
}
// both wrapper and handler should panic
rsp = pb.Response{}
if err := cc.Invoke(context.Background(), "/test.Test/Call", &pb.Request{Name: "Panic"}, &rsp); err == nil {
t.Fatal("this must return error, as wrapper and handler should be panic")
}
}
// TestGRPCServerWithPanicWrapper test grpc server with panic handler
// gRPC server should not crash when handler crashed
func TestGRPCServerWithPanicHandler(t *testing.T) {
r := rmemory.NewRegistry()
b := bmemory.NewBroker()
tr := tgrpc.NewTransport()
s := gsrv.NewServer(
server.Broker(b),
server.Name("foo"),
server.Registry(r),
server.Transport(tr),
)
h := &testServer{}
pb.RegisterTestHandler(s, h)
if err := s.Start(); err != nil {
t.Fatalf("failed to start: %v", err)
}
// check registration
services, err := r.GetService("foo")
if err != nil || len(services) == 0 {
t.Fatalf("failed to get service: %v # %d", err, len(services))
}
defer func() {
if err := s.Stop(); err != nil {
t.Fatalf("failed to stop: %v", err)
}
}()
cc, err := grpc.Dial(s.Options().Address, grpc.WithInsecure())
if err != nil {
t.Fatalf("failed to dial server: %v", err)
}
rsp := pb.Response{}
if err := cc.Invoke(context.Background(), "/test.Test/Call", &pb.Request{Name: "Panic"}, &rsp); err == nil {
t.Fatal("this must return error, as handler should be panic")
}
} }

View File

@ -3,8 +3,8 @@ package grpc
import ( import (
"reflect" "reflect"
"github.com/micro/go-micro/v3/registry" "github.com/unistack-org/micro/v3/registry"
"github.com/micro/go-micro/v3/server" "github.com/unistack-org/micro/v3/server"
) )
type rpcHandler struct { type rpcHandler struct {

View File

@ -5,10 +5,7 @@ import (
"crypto/tls" "crypto/tls"
"net" "net"
"github.com/micro/go-micro/v3/broker/http" "github.com/unistack-org/micro/v3/server"
"github.com/micro/go-micro/v3/codec"
"github.com/micro/go-micro/v3/registry/mdns"
"github.com/micro/go-micro/v3/server"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/encoding" "google.golang.org/grpc/encoding"
) )
@ -19,6 +16,7 @@ type netListener struct{}
type maxMsgSizeKey struct{} type maxMsgSizeKey struct{}
type maxConnKey struct{} type maxConnKey struct{}
type tlsAuth struct{} type tlsAuth struct{}
type reflectionKey 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
func Codec(contentType string, c encoding.Codec) server.Option { func Codec(contentType string, c encoding.Codec) server.Option {
@ -63,23 +61,7 @@ func MaxMsgSize(s int) server.Option {
return setServerOption(maxMsgSizeKey{}, s) return setServerOption(maxMsgSizeKey{}, s)
} }
func newOptions(opt ...server.Option) server.Options { // Reflection enables reflection support in grpc server
opts := server.Options{ func Reflection(b bool) server.Option {
Codecs: make(map[string]codec.NewCodec), return setServerOption(reflectionKey{}, b)
Metadata: map[string]string{},
Broker: http.NewBroker(),
Registry: mdns.NewRegistry(),
Address: server.DefaultAddress,
Name: server.DefaultName,
Id: server.DefaultId,
Version: server.DefaultVersion,
RegisterInterval: server.DefaultRegisterInterval,
RegisterTTL: server.DefaultRegisterTTL,
}
for _, o := range opt {
o(&opts)
}
return opts
} }

View File

@ -1,292 +1,222 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// source: server/grpc/proto/test.proto // versions:
// protoc-gen-go v1.25.0-devel
// protoc v3.6.1
// source: test.proto
package test package helloworld
import ( import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
_ "google.golang.org/genproto/googleapis/api/annotations" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
grpc "google.golang.org/grpc" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
codes "google.golang.org/grpc/codes" reflect "reflect"
status "google.golang.org/grpc/status" sync "sync"
math "math"
) )
// Reference imports to suppress errors if they are not otherwise used. const (
var _ = proto.Marshal // Verify that this generated code is sufficiently up-to-date.
var _ = fmt.Errorf _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
var _ = math.Inf // Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion that a sufficiently up-to-date version
// is compatible with the proto package it is being compiled against. // of the legacy proto package is being used.
// A compilation error at this line likely means your copy of the const _ = proto.ProtoPackageIsVersion4
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Request struct { type Request struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
} }
func (m *Request) Reset() { *m = Request{} } func (x *Request) Reset() {
func (m *Request) String() string { return proto.CompactTextString(m) } *x = Request{}
if protoimpl.UnsafeEnabled {
mi := &file_test_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Request) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Request) ProtoMessage() {} func (*Request) ProtoMessage() {}
func (x *Request) ProtoReflect() protoreflect.Message {
mi := &file_test_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 Request.ProtoReflect.Descriptor instead.
func (*Request) Descriptor() ([]byte, []int) { func (*Request) Descriptor() ([]byte, []int) {
return fileDescriptor_bb9c685b7640cf1e, []int{0} return file_test_proto_rawDescGZIP(), []int{0}
} }
func (m *Request) XXX_Unmarshal(b []byte) error { func (x *Request) GetUuid() string {
return xxx_messageInfo_Request.Unmarshal(m, b) if x != nil {
} return x.Uuid
func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Request.Marshal(b, m, deterministic)
}
func (m *Request) XXX_Merge(src proto.Message) {
xxx_messageInfo_Request.Merge(m, src)
}
func (m *Request) XXX_Size() int {
return xxx_messageInfo_Request.Size(m)
}
func (m *Request) XXX_DiscardUnknown() {
xxx_messageInfo_Request.DiscardUnknown(m)
}
var xxx_messageInfo_Request proto.InternalMessageInfo
func (m *Request) GetUuid() string {
if m != nil {
return m.Uuid
} }
return "" return ""
} }
func (m *Request) GetName() string { func (x *Request) GetName() string {
if m != nil { if x != nil {
return m.Name return x.Name
} }
return "" return ""
} }
type Response struct { type Response struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
} }
func (m *Response) Reset() { *m = Response{} } func (x *Response) Reset() {
func (m *Response) String() string { return proto.CompactTextString(m) } *x = Response{}
if protoimpl.UnsafeEnabled {
mi := &file_test_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Response) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Response) ProtoMessage() {} func (*Response) ProtoMessage() {}
func (x *Response) ProtoReflect() protoreflect.Message {
mi := &file_test_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 Response.ProtoReflect.Descriptor instead.
func (*Response) Descriptor() ([]byte, []int) { func (*Response) Descriptor() ([]byte, []int) {
return fileDescriptor_bb9c685b7640cf1e, []int{1} return file_test_proto_rawDescGZIP(), []int{1}
} }
func (m *Response) XXX_Unmarshal(b []byte) error { func (x *Response) GetMsg() string {
return xxx_messageInfo_Response.Unmarshal(m, b) if x != nil {
} return x.Msg
func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Response.Marshal(b, m, deterministic)
}
func (m *Response) XXX_Merge(src proto.Message) {
xxx_messageInfo_Response.Merge(m, src)
}
func (m *Response) XXX_Size() int {
return xxx_messageInfo_Response.Size(m)
}
func (m *Response) XXX_DiscardUnknown() {
xxx_messageInfo_Response.DiscardUnknown(m)
}
var xxx_messageInfo_Response proto.InternalMessageInfo
func (m *Response) GetMsg() string {
if m != nil {
return m.Msg
} }
return "" return ""
} }
func init() { var File_test_proto protoreflect.FileDescriptor
proto.RegisterType((*Request)(nil), "Request")
proto.RegisterType((*Response)(nil), "Response") var file_test_proto_rawDesc = []byte{
0x0a, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x68, 0x65,
0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x22, 0x31, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x1c, 0x0a, 0x08, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x32, 0x3b, 0x0a, 0x04, 0x54, 0x65, 0x73,
0x74, 0x12, 0x33, 0x0a, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x13, 0x2e, 0x68, 0x65, 0x6c, 0x6c,
0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14,
0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
func init() { proto.RegisterFile("server/grpc/proto/test.proto", fileDescriptor_bb9c685b7640cf1e) } var (
file_test_proto_rawDescOnce sync.Once
file_test_proto_rawDescData = file_test_proto_rawDesc
)
var fileDescriptor_bb9c685b7640cf1e = []byte{ func file_test_proto_rawDescGZIP() []byte {
// 261 bytes of a gzipped FileDescriptorProto file_test_proto_rawDescOnce.Do(func() {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x29, 0x4e, 0x2d, 0x2a, file_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_proto_rawDescData)
0x4b, 0x2d, 0xd2, 0x4f, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0xd7, 0x2f, 0x49, })
0x2d, 0x2e, 0xd1, 0x03, 0x33, 0xa5, 0x64, 0xd2, 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0x13, 0x0b, return file_test_proto_rawDescData
0x32, 0xf5, 0x13, 0xf3, 0xf2, 0xf2, 0x4b, 0x12, 0x4b, 0x32, 0xf3, 0xf3, 0x8a, 0x21, 0xb2, 0x4a,
0x86, 0x5c, 0xec, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x42, 0x5c, 0x2c, 0xa5, 0xa5,
0x99, 0x29, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x60, 0x36, 0x48, 0x2c, 0x2f, 0x31, 0x37,
0x55, 0x82, 0x09, 0x22, 0x06, 0x62, 0x2b, 0xc9, 0x70, 0x71, 0x04, 0xa5, 0x16, 0x17, 0xe4, 0xe7,
0x15, 0xa7, 0x0a, 0x09, 0x70, 0x31, 0xe7, 0x16, 0xa7, 0x43, 0xb5, 0x80, 0x98, 0x46, 0xcf, 0x18,
0xb9, 0x58, 0x42, 0x40, 0xc6, 0x39, 0x70, 0xb1, 0x38, 0x27, 0xe6, 0xe4, 0x08, 0x71, 0xe8, 0x41,
0x2d, 0x90, 0xe2, 0xd4, 0x83, 0xe9, 0x53, 0x52, 0x6e, 0xba, 0xfc, 0x64, 0x32, 0x93, 0xac, 0x92,
0x04, 0xd8, 0x59, 0x65, 0x06, 0x60, 0x07, 0xeb, 0x27, 0x27, 0xe6, 0xe4, 0xe8, 0x57, 0x83, 0x2c,
0xae, 0xb5, 0x62, 0xd4, 0x12, 0x72, 0xe3, 0xe2, 0x00, 0x99, 0x10, 0x90, 0x5c, 0x94, 0x8a, 0xdd,
0x14, 0x55, 0xb0, 0x29, 0xf2, 0x4a, 0x52, 0x71, 0x98, 0xc6, 0x14, 0x24, 0x17, 0xa5, 0xea, 0xdb,
0xab, 0x80, 0xcc, 0x09, 0xe1, 0xe2, 0x87, 0x99, 0xe3, 0x99, 0x57, 0x96, 0x98, 0x93, 0x99, 0x82,
0xdd, 0x38, 0x1d, 0xb0, 0x71, 0x6a, 0x4a, 0x8a, 0xb8, 0x8c, 0xcb, 0x84, 0xe8, 0xd6, 0xb7, 0xb7,
0x62, 0xd4, 0x4a, 0x62, 0x03, 0x07, 0xa0, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xf6, 0x32, 0x18,
0x0f, 0x7e, 0x01, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. var file_test_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var _ context.Context var file_test_proto_goTypes = []interface{}{
var _ grpc.ClientConn (*Request)(nil), // 0: helloworld.Request
(*Response)(nil), // 1: helloworld.Response
// This is a compile-time assertion to ensure that this generated file }
// is compatible with the grpc package it is being compiled against. var file_test_proto_depIdxs = []int32{
const _ = grpc.SupportPackageIsVersion4 0, // 0: helloworld.Test.Call:input_type -> helloworld.Request
1, // 1: helloworld.Test.Call:output_type -> helloworld.Response
// TestClient is the client API for Test service. 1, // [1:2] is the sub-list for method output_type
// 0, // [0:1] is the sub-list for method input_type
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 0, // [0:0] is the sub-list for extension type_name
type TestClient interface { 0, // [0:0] is the sub-list for extension extendee
Call(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) 0, // [0:0] is the sub-list for field type_name
CallPcre(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error)
CallPcreInvalid(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error)
} }
type testClient struct { func init() { file_test_proto_init() }
cc *grpc.ClientConn func file_test_proto_init() {
} if File_test_proto != nil {
return
func NewTestClient(cc *grpc.ClientConn) TestClient {
return &testClient{cc}
}
func (c *testClient) Call(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) {
out := new(Response)
err := c.cc.Invoke(ctx, "/Test/Call", in, out, opts...)
if err != nil {
return nil, err
} }
return out, nil if !protoimpl.UnsafeEnabled {
} file_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Request); i {
func (c *testClient) CallPcre(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) { case 0:
out := new(Response) return &v.state
err := c.cc.Invoke(ctx, "/Test/CallPcre", in, out, opts...) case 1:
if err != nil { return &v.sizeCache
return nil, err case 2:
return &v.unknownFields
default:
return nil
} }
return out, nil
}
func (c *testClient) CallPcreInvalid(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) {
out := new(Response)
err := c.cc.Invoke(ctx, "/Test/CallPcreInvalid", in, out, opts...)
if err != nil {
return nil, err
} }
return out, nil file_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
} switch v := v.(*Response); i {
case 0:
// TestServer is the server API for Test service. return &v.state
type TestServer interface { case 1:
Call(context.Context, *Request) (*Response, error) return &v.sizeCache
CallPcre(context.Context, *Request) (*Response, error) case 2:
CallPcreInvalid(context.Context, *Request) (*Response, error) return &v.unknownFields
} default:
return nil
// UnimplementedTestServer can be embedded to have forward compatible implementations.
type UnimplementedTestServer struct {
}
func (*UnimplementedTestServer) Call(ctx context.Context, req *Request) (*Response, error) {
return nil, status.Errorf(codes.Unimplemented, "method Call not implemented")
}
func (*UnimplementedTestServer) CallPcre(ctx context.Context, req *Request) (*Response, error) {
return nil, status.Errorf(codes.Unimplemented, "method CallPcre not implemented")
}
func (*UnimplementedTestServer) CallPcreInvalid(ctx context.Context, req *Request) (*Response, error) {
return nil, status.Errorf(codes.Unimplemented, "method CallPcreInvalid not implemented")
}
func RegisterTestServer(s *grpc.Server, srv TestServer) {
s.RegisterService(&_Test_serviceDesc, srv)
}
func _Test_Call_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Request)
if err := dec(in); err != nil {
return nil, err
} }
if interceptor == nil {
return srv.(TestServer).Call(ctx, in)
} }
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/Test/Call",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { type x struct{}
return srv.(TestServer).Call(ctx, req.(*Request)) out := protoimpl.TypeBuilder{
} File: protoimpl.DescBuilder{
return interceptor(ctx, in, info, handler) GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
} RawDescriptor: file_test_proto_rawDesc,
NumEnums: 0,
func _Test_CallPcre_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { NumMessages: 2,
in := new(Request) NumExtensions: 0,
if err := dec(in); err != nil { NumServices: 1,
return nil, err
}
if interceptor == nil {
return srv.(TestServer).CallPcre(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/Test/CallPcre",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TestServer).CallPcre(ctx, req.(*Request))
}
return interceptor(ctx, in, info, handler)
}
func _Test_CallPcreInvalid_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Request)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TestServer).CallPcreInvalid(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/Test/CallPcreInvalid",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TestServer).CallPcreInvalid(ctx, req.(*Request))
}
return interceptor(ctx, in, info, handler)
}
var _Test_serviceDesc = grpc.ServiceDesc{
ServiceName: "Test",
HandlerType: (*TestServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Call",
Handler: _Test_Call_Handler,
}, },
{ GoTypes: file_test_proto_goTypes,
MethodName: "CallPcre", DependencyIndexes: file_test_proto_depIdxs,
Handler: _Test_CallPcre_Handler, MessageInfos: file_test_proto_msgTypes,
}, }.Build()
{ File_test_proto = out.File
MethodName: "CallPcreInvalid", file_test_proto_rawDesc = nil
Handler: _Test_CallPcreInvalid_Handler, file_test_proto_goTypes = nil
}, file_test_proto_depIdxs = nil
},
Streams: []grpc.StreamDesc{},
Metadata: "server/grpc/proto/test.proto",
} }

View File

@ -1,20 +1,19 @@
// Code generated by protoc-gen-micro. DO NOT EDIT. // Code generated by protoc-gen-micro. DO NOT EDIT.
// source: server/grpc/proto/test.proto // source: test.proto
package test package helloworld
import ( import (
fmt "fmt" fmt "fmt"
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
_ "google.golang.org/genproto/googleapis/api/annotations"
math "math" math "math"
) )
import ( import (
context "context" context "context"
api "github.com/micro/go-micro/v3/api" api "github.com/unistack-org/micro/v3/api"
client "github.com/micro/go-micro/v3/client" client "github.com/unistack-org/micro/v3/client"
server "github.com/micro/go-micro/v3/server" server "github.com/unistack-org/micro/v3/server"
) )
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -37,37 +36,13 @@ var _ server.Option
// Api Endpoints for Test service // Api Endpoints for Test service
func NewTestEndpoints() []*api.Endpoint { func NewTestEndpoints() []*api.Endpoint {
return []*api.Endpoint{ return []*api.Endpoint{}
&api.Endpoint{
Name: "Test.Call",
Path: []string{"/api/v0/test/call/{uuid}"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
&api.Endpoint{
Name: "Test.CallPcre",
Path: []string{"^/api/v0/test/call/pcre/?$"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
&api.Endpoint{
Name: "Test.CallPcreInvalid",
Path: []string{"^/api/v0/test/call/pcre/invalid/?"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
}
} }
// Client API for Test service // Client API for Test service
type TestService interface { type TestService interface {
Call(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error) Call(ctx context.Context, req *Request, opts ...client.CallOption) (*Response, error)
CallPcre(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error)
CallPcreInvalid(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error)
} }
type testService struct { type testService struct {
@ -82,75 +57,29 @@ func NewTestService(name string, c client.Client) TestService {
} }
} }
func (c *testService) Call(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error) { func (c *testService) Call(ctx context.Context, req *Request, opts ...client.CallOption) (*Response, error) {
req := c.c.NewRequest(c.name, "Test.Call", in) rsp := &Response{}
out := new(Response) err := c.c.Call(ctx, c.c.NewRequest(c.name, "Test.Call", req), rsp, opts...)
err := c.c.Call(ctx, req, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return out, nil return rsp, nil
}
func (c *testService) CallPcre(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error) {
req := c.c.NewRequest(c.name, "Test.CallPcre", in)
out := new(Response)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *testService) CallPcreInvalid(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error) {
req := c.c.NewRequest(c.name, "Test.CallPcreInvalid", in)
out := new(Response)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
} }
// Server API for Test service // Server API for Test service
type TestHandler interface { type TestHandler interface {
Call(context.Context, *Request, *Response) error Call(context.Context, *Request, *Response) error
CallPcre(context.Context, *Request, *Response) error
CallPcreInvalid(context.Context, *Request, *Response) error
} }
func RegisterTestHandler(s server.Server, hdlr TestHandler, opts ...server.HandlerOption) error { func RegisterTestHandler(s server.Server, hdlr TestHandler, opts ...server.HandlerOption) error {
type test interface { type test interface {
Call(ctx context.Context, in *Request, out *Response) error Call(ctx context.Context, req *Request, rsp *Response) error
CallPcre(ctx context.Context, in *Request, out *Response) error
CallPcreInvalid(ctx context.Context, in *Request, out *Response) error
} }
type Test struct { type Test struct {
test test
} }
h := &testHandler{hdlr} h := &testHandler{hdlr}
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "Test.Call",
Path: []string{"/api/v0/test/call/{uuid}"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "Test.CallPcre",
Path: []string{"^/api/v0/test/call/pcre/?$"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "Test.CallPcreInvalid",
Path: []string{"^/api/v0/test/call/pcre/invalid/?"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
return s.Handle(s.NewHandler(&Test{h}, opts...)) return s.Handle(s.NewHandler(&Test{h}, opts...))
} }
@ -158,14 +87,6 @@ type testHandler struct {
TestHandler TestHandler
} }
func (h *testHandler) Call(ctx context.Context, in *Request, out *Response) error { func (h *testHandler) Call(ctx context.Context, req *Request, rsp *Response) error {
return h.TestHandler.Call(ctx, in, out) return h.TestHandler.Call(ctx, req, rsp)
}
func (h *testHandler) CallPcre(ctx context.Context, in *Request, out *Response) error {
return h.TestHandler.CallPcre(ctx, in, out)
}
func (h *testHandler) CallPcreInvalid(ctx context.Context, in *Request, out *Response) error {
return h.TestHandler.CallPcreInvalid(ctx, in, out)
} }

View File

@ -1,17 +1,9 @@
syntax = "proto3"; syntax = "proto3";
import "google/api/annotations.proto"; package helloworld;
service Test { service Test {
rpc Call(Request) returns (Response) { rpc Call(Request) returns (Response) {}
option (google.api.http) = { post: "/api/v0/test/call/{uuid}"; body:"*"; };
};
rpc CallPcre(Request) returns (Response) {
option (google.api.http) = { post: "^/api/v0/test/call/pcre/?$"; body:"*"; };
};
rpc CallPcreInvalid(Request) returns (Response) {
option (google.api.http) = { post: "^/api/v0/test/call/pcre/invalid/?"; body:"*"; };
};
} }
message Request { message Request {

90
proto/test_grpc.pb.go Normal file
View File

@ -0,0 +1,90 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package helloworld
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.
const _ = grpc.SupportPackageIsVersion6
// TestClient is the client API for Test 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 TestClient interface {
Call(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error)
}
type testClient struct {
cc grpc.ClientConnInterface
}
func NewTestClient(cc grpc.ClientConnInterface) TestClient {
return &testClient{cc}
}
func (c *testClient) Call(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) {
out := new(Response)
err := c.cc.Invoke(ctx, "/helloworld.Test/Call", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// TestServer is the server API for Test service.
// All implementations must embed UnimplementedTestServer
// for forward compatibility
type TestServer interface {
Call(context.Context, *Request) (*Response, error)
mustEmbedUnimplementedTestServer()
}
// UnimplementedTestServer must be embedded to have forward compatible implementations.
type UnimplementedTestServer struct {
}
func (*UnimplementedTestServer) Call(context.Context, *Request) (*Response, error) {
return nil, status.Errorf(codes.Unimplemented, "method Call not implemented")
}
func (*UnimplementedTestServer) mustEmbedUnimplementedTestServer() {}
func RegisterTestServer(s *grpc.Server, srv TestServer) {
s.RegisterService(&_Test_serviceDesc, srv)
}
func _Test_Call_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Request)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TestServer).Call(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/helloworld.Test/Call",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TestServer).Call(ctx, req.(*Request))
}
return interceptor(ctx, in, info, handler)
}
var _Test_serviceDesc = grpc.ServiceDesc{
ServiceName: "helloworld.Test",
HandlerType: (*TestServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Call",
Handler: _Test_Call_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "test.proto",
}

View File

@ -1,8 +1,8 @@
package grpc package grpc
import ( import (
"github.com/micro/go-micro/v3/codec" "github.com/unistack-org/micro/v3/codec"
"github.com/micro/go-micro/v3/codec/bytes" "github.com/unistack-org/micro-codec-bytes"
) )
type rpcRequest struct { type rpcRequest struct {

View File

@ -1,7 +1,7 @@
package grpc package grpc
import ( import (
"github.com/micro/go-micro/v3/codec" "github.com/unistack-org/micro/v3/codec"
) )
type rpcResponse struct { type rpcResponse struct {

View File

@ -8,14 +8,14 @@ package grpc
import ( import (
"context" "context"
"errors" "fmt"
"reflect" "reflect"
"sync" "sync"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
"github.com/micro/go-micro/v3/logger" "github.com/unistack-org/micro/v3/logger"
"github.com/micro/go-micro/v3/server" "github.com/unistack-org/micro/v3/server"
) )
var ( var (
@ -32,6 +32,8 @@ type methodType struct {
stream bool stream bool
} }
type reflectionType func(context.Context, server.Stream) error
type service struct { type service struct {
name string // name of service name string // name of service
rcvr reflect.Value // receiver of methods for the service rcvr reflect.Value // receiver of methods for the service
@ -41,8 +43,9 @@ type service struct {
// server represents an RPC Server. // server represents an RPC Server.
type rServer struct { type rServer struct {
mu sync.Mutex // protects the serviceMap mu sync.RWMutex // protects the serviceMap
serviceMap map[string]*service serviceMap map[string]*service
reflection bool
} }
// Is this an exported - upper case - name? // Is this an exported - upper case - name?
@ -86,7 +89,7 @@ func prepareEndpoint(method reflect.Method) *methodType {
replyType = mtype.In(3) replyType = mtype.In(3)
contextType = mtype.In(1) contextType = mtype.In(1)
default: default:
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Errorf("method %v of %v has wrong number of ins: %v", mname, mtype, mtype.NumIn()) logger.Errorf("method %v of %v has wrong number of ins: %v", mname, mtype, mtype.NumIn())
} }
return nil return nil
@ -96,7 +99,7 @@ func prepareEndpoint(method reflect.Method) *methodType {
// check stream type // check stream type
streamType := reflect.TypeOf((*server.Stream)(nil)).Elem() streamType := reflect.TypeOf((*server.Stream)(nil)).Elem()
if !argType.Implements(streamType) { if !argType.Implements(streamType) {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Errorf("%v argument does not implement Streamer interface: %v", mname, argType) logger.Errorf("%v argument does not implement Streamer interface: %v", mname, argType)
} }
return nil return nil
@ -106,14 +109,14 @@ func prepareEndpoint(method reflect.Method) *methodType {
// First arg need not be a pointer. // First arg need not be a pointer.
if !isExportedOrBuiltinType(argType) { if !isExportedOrBuiltinType(argType) {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Errorf("%v argument type not exported: %v", mname, argType) logger.Errorf("%v argument type not exported: %v", mname, argType)
} }
return nil return nil
} }
if replyType.Kind() != reflect.Ptr { if replyType.Kind() != reflect.Ptr {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Errorf("method %v reply type not a pointer: %v", mname, replyType) logger.Errorf("method %v reply type not a pointer: %v", mname, replyType)
} }
return nil return nil
@ -121,7 +124,7 @@ func prepareEndpoint(method reflect.Method) *methodType {
// Reply type must be exported. // Reply type must be exported.
if !isExportedOrBuiltinType(replyType) { if !isExportedOrBuiltinType(replyType) {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Errorf("method %v reply type not exported: %v", mname, replyType) logger.Errorf("method %v reply type not exported: %v", mname, replyType)
} }
return nil return nil
@ -130,14 +133,14 @@ func prepareEndpoint(method reflect.Method) *methodType {
// Endpoint() needs one out. // Endpoint() needs one out.
if mtype.NumOut() != 1 { if mtype.NumOut() != 1 {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Errorf("method %v has wrong number of outs: %v", mname, mtype.NumOut()) logger.Errorf("method %v has wrong number of outs: %v", mname, mtype.NumOut())
} }
return nil return nil
} }
// The return type of the method must be error. // The return type of the method must be error.
if returnType := mtype.Out(0); returnType != typeOfError { if returnType := mtype.Out(0); returnType != typeOfError {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Errorf("method %v returns %v not error", mname, returnType.String()) logger.Errorf("method %v returns %v not error", mname, returnType.String())
} }
return nil return nil
@ -151,22 +154,22 @@ func (server *rServer) register(rcvr interface{}) error {
if server.serviceMap == nil { if server.serviceMap == nil {
server.serviceMap = make(map[string]*service) server.serviceMap = make(map[string]*service)
} }
s := new(service) s := &service{}
s.typ = reflect.TypeOf(rcvr) s.typ = reflect.TypeOf(rcvr)
s.rcvr = reflect.ValueOf(rcvr) s.rcvr = reflect.ValueOf(rcvr)
sname := reflect.Indirect(s.rcvr).Type().Name() sname := reflect.Indirect(s.rcvr).Type().Name()
if sname == "" { if sname == "" {
logger.Fatalf("rpc: no service name for type %v", s.typ.String()) return fmt.Errorf("rpc: no service name for type %v", s.typ.String())
} }
if !isExported(sname) { if !isExported(sname) {
s := "rpc Register: type " + sname + " is not exported" s := "rpc Register: type " + sname + " is not exported"
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Error(s) logger.Error(s)
} }
return errors.New(s) return fmt.Errorf(s)
} }
if _, present := server.serviceMap[sname]; present { if _, present := server.serviceMap[sname]; present {
return errors.New("rpc: service already defined: " + sname) return fmt.Errorf("rpc: service already defined: " + sname)
} }
s.name = sname s.name = sname
s.method = make(map[string]*methodType) s.method = make(map[string]*methodType)
@ -181,10 +184,10 @@ func (server *rServer) register(rcvr interface{}) error {
if len(s.method) == 0 { if len(s.method) == 0 {
s := "rpc Register: type " + sname + " has no exported methods of suitable type" s := "rpc Register: type " + sname + " has no exported methods of suitable type"
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Error(s) logger.Error(s)
} }
return errors.New(s) return fmt.Errorf(s)
} }
server.serviceMap[s.name] = s server.serviceMap[s.name] = s
return nil return nil

View File

@ -3,7 +3,7 @@ package grpc
import ( import (
"context" "context"
"github.com/micro/go-micro/v3/server" "github.com/unistack-org/micro/v3/server"
"google.golang.org/grpc" "google.golang.org/grpc"
) )

View File

@ -7,12 +7,12 @@ import (
"runtime/debug" "runtime/debug"
"strings" "strings"
"github.com/micro/go-micro/v3/broker" "github.com/unistack-org/micro/v3/broker"
"github.com/micro/go-micro/v3/errors" "github.com/unistack-org/micro/v3/errors"
"github.com/micro/go-micro/v3/logger" "github.com/unistack-org/micro/v3/logger"
"github.com/micro/go-micro/v3/metadata" "github.com/unistack-org/micro/v3/metadata"
"github.com/micro/go-micro/v3/registry" "github.com/unistack-org/micro/v3/registry"
"github.com/micro/go-micro/v3/server" "github.com/unistack-org/micro/v3/server"
) )
const ( const (
@ -36,10 +36,7 @@ type subscriber struct {
} }
func newSubscriber(topic string, sub interface{}, opts ...server.SubscriberOption) server.Subscriber { func newSubscriber(topic string, sub interface{}, opts ...server.SubscriberOption) server.Subscriber {
options := server.SubscriberOptions{ options := server.NewSubscriberOptions()
AutoAck: true,
}
for _, o := range opts { for _, o := range opts {
o(&options) o(&options)
} }
@ -167,11 +164,10 @@ func validateSubscriber(sub server.Subscriber) error {
} }
func (g *grpcServer) createSubHandler(sb *subscriber, opts server.Options) broker.Handler { func (g *grpcServer) createSubHandler(sb *subscriber, opts server.Options) broker.Handler {
return func(msg *broker.Message) (err error) { return func(p broker.Event) (err error) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
if logger.V(logger.ErrorLevel, logger.DefaultLogger) { if logger.V(logger.ErrorLevel) {
logger.Error("panic recovered: ", r) logger.Error("panic recovered: ", r)
logger.Error(string(debug.Stack())) logger.Error(string(debug.Stack()))
} }
@ -179,6 +175,7 @@ func (g *grpcServer) createSubHandler(sb *subscriber, opts server.Options) broke
} }
}() }()
msg := p.Message()
// if we don't have headers, create empty map // if we don't have headers, create empty map
if msg.Header == nil { if msg.Header == nil {
msg.Header = make(map[string]string) msg.Header = make(map[string]string)

49
util.go
View File

@ -1,49 +0,0 @@
package grpc
import (
"context"
"io"
"os"
"sync"
"google.golang.org/grpc/codes"
)
// convertCode converts a standard Go error into its canonical code. Note that
// this is only used to translate the error returned by the server applications.
func convertCode(err error) codes.Code {
switch err {
case nil:
return codes.OK
case io.EOF:
return codes.OutOfRange
case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF:
return codes.FailedPrecondition
case os.ErrInvalid:
return codes.InvalidArgument
case context.Canceled:
return codes.Canceled
case context.DeadlineExceeded:
return codes.DeadlineExceeded
}
switch {
case os.IsExist(err):
return codes.AlreadyExists
case os.IsNotExist(err):
return codes.NotFound
case os.IsPermission(err):
return codes.PermissionDenied
}
return codes.Unknown
}
func wait(ctx context.Context) *sync.WaitGroup {
if ctx == nil {
return nil
}
wg, ok := ctx.Value("wait").(*sync.WaitGroup)
if !ok {
return nil
}
return wg
}