Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
171 additions
and
146 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Code in this file is copied from net/rpc with minimum changes. | ||
// | ||
// Copyright 2009 The Go Authors. All rights reserved. | ||
|
||
package reflectx | ||
|
||
import ( | ||
"go/token" | ||
"reflect" | ||
) | ||
|
||
// suitableMethods returns suitable Rpc methods of typ. | ||
func suitableMethods(typ reflect.Type) (methods []string) { | ||
for m := 0; m < typ.NumMethod(); m++ { | ||
method := typ.Method(m) | ||
mtype := method.Type | ||
mname := method.Name | ||
// Method must be exported. | ||
if method.PkgPath != "" { | ||
continue | ||
} | ||
// Method needs three ins: receiver, *args, *reply. | ||
if mtype.NumIn() != 3 { //nolint:gomnd // net/rpc | ||
continue | ||
} | ||
// First arg need not be a pointer. | ||
argType := mtype.In(1) | ||
if !isExportedOrBuiltinType(argType) { | ||
continue | ||
} | ||
// Second arg must be a pointer. | ||
replyType := mtype.In(2) //nolint:gomnd // net/rpc | ||
if replyType.Kind() != reflect.Ptr { | ||
continue | ||
} | ||
// Reply type must be exported. | ||
if !isExportedOrBuiltinType(replyType) { | ||
continue | ||
} | ||
// Method needs one out. | ||
if mtype.NumOut() != 1 { | ||
continue | ||
} | ||
// The return type of the method must be error. | ||
if returnType := mtype.Out(0); returnType != typeOfError { | ||
continue | ||
} | ||
methods = append(methods, mname) | ||
} | ||
return methods | ||
} | ||
|
||
// Precompute the reflect type for error. Can't use error directly | ||
// because Typeof takes an empty interface value. This is annoying. | ||
var typeOfError = reflect.TypeOf((*error)(nil)).Elem() //nolint:gochecknoglobals // net/rpc | ||
|
||
// Is this type exported or a builtin? | ||
func isExportedOrBuiltinType(t reflect.Type) bool { | ||
for t.Kind() == reflect.Ptr { | ||
t = t.Elem() | ||
} | ||
// PkgPath will be non-empty even for an exported type, | ||
// so we need to check the type name as well. | ||
return token.IsExported(t.Name()) || t.PkgPath() == "" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,9 @@ | ||
// Code in this file is copied from net/rpc with minimum changes. | ||
// | ||
// Copyright 2009 The Go Authors. All rights reserved. | ||
|
||
package reflectx | ||
|
||
import ( | ||
"go/token" | ||
"reflect" | ||
) | ||
|
||
// suitableMethods returns suitable Rpc methods of typ. | ||
func suitableMethods(typ reflect.Type) (methods []string) { | ||
for m := 0; m < typ.NumMethod(); m++ { | ||
method := typ.Method(m) | ||
mtype := method.Type | ||
mname := method.Name | ||
// Method must be exported. | ||
if method.PkgPath != "" { | ||
continue | ||
} | ||
// Method needs three ins: receiver, *args, *reply. | ||
if mtype.NumIn() != 3 { //nolint:gomnd // net/rpc | ||
continue | ||
} | ||
// First arg need not be a pointer. | ||
argType := mtype.In(1) | ||
if !isExportedOrBuiltinType(argType) { | ||
continue | ||
} | ||
// Second arg must be a pointer. | ||
replyType := mtype.In(2) //nolint:gomnd // net/rpc | ||
if replyType.Kind() != reflect.Ptr { | ||
continue | ||
} | ||
// Reply type must be exported. | ||
if !isExportedOrBuiltinType(replyType) { | ||
continue | ||
} | ||
// Method needs one out. | ||
if mtype.NumOut() != 1 { | ||
continue | ||
} | ||
// The return type of the method must be error. | ||
if returnType := mtype.Out(0); returnType != typeOfError { | ||
continue | ||
} | ||
methods = append(methods, mname) | ||
} | ||
return methods | ||
} | ||
|
||
// Precompute the reflect type for error. Can't use error directly | ||
// because Typeof takes an empty interface value. This is annoying. | ||
var typeOfError = reflect.TypeOf((*error)(nil)).Elem() //nolint:gochecknoglobals // net/rpc | ||
import "reflect" | ||
|
||
// Is this type exported or a builtin? | ||
func isExportedOrBuiltinType(t reflect.Type) bool { | ||
for t.Kind() == reflect.Ptr { | ||
t = t.Elem() | ||
} | ||
// PkgPath will be non-empty even for an exported type, | ||
// so we need to check the type name as well. | ||
return token.IsExported(t.Name()) || t.PkgPath() == "" | ||
// RPCMethodsOf require receiver value used for net/rpc.Register and | ||
// returns all it RPC methods (detected in same way as net/rpc does). | ||
func RPCMethodsOf(v interface{}) []string { | ||
return suitableMethods(reflect.TypeOf(v)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package serve | ||
|
||
import ( | ||
"net" | ||
|
||
"github.com/powerman/structlog" | ||
"google.golang.org/grpc" | ||
|
||
"github.com/powerman/go-monolith-example/pkg/def" | ||
"github.com/powerman/go-monolith-example/pkg/netx" | ||
) | ||
|
||
// GRPC starts gRPC server on addr, logged as service. | ||
// It runs until failed or ctx.Done. | ||
func GRPC(ctx Ctx, addr netx.Addr, srv *grpc.Server, service string) (err error) { | ||
log := structlog.FromContext(ctx, nil).New(def.LogServer, service) | ||
|
||
ln, err := net.Listen("tcp", addr.String()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
log.Info("serve", def.LogHost, addr.Host(), def.LogPort, addr.Port()) | ||
errc := make(chan error, 1) | ||
go func() { errc <- srv.Serve(ln) }() | ||
|
||
select { | ||
case err = <-errc: | ||
case <-ctx.Done(): | ||
srv.GracefulStop() // It will not interrupt streaming. | ||
} | ||
if err != nil { | ||
return log.Err("failed to serve", "err", err) | ||
} | ||
log.Info("shutdown") | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package serve | ||
|
||
import ( | ||
"crypto/tls" | ||
"net/http" | ||
"net/rpc" | ||
|
||
"github.com/powerman/rpc-codec/jsonrpc2" | ||
|
||
"github.com/powerman/go-monolith-example/pkg/netx" | ||
) | ||
|
||
// RPC starts HTTP server on addr path /rpc using rcvr as JSON-RPC 2.0 | ||
// handler. | ||
func RPC(ctx Ctx, addr netx.Addr, tlsConfig *tls.Config, rcvr interface{}) error { | ||
return RPCName(ctx, addr, tlsConfig, rcvr, "") | ||
} | ||
|
||
// RPCName starts HTTP server on addr path /rpc using rcvr as JSON-RPC 2.0 | ||
// handler but uses the provided name for the type instead of the | ||
// receiver's concrete type. | ||
func RPCName(ctx Ctx, addr netx.Addr, tlsConfig *tls.Config, rcvr interface{}, name string) (err error) { | ||
srv := rpc.NewServer() | ||
if name != "" { | ||
err = srv.RegisterName(name, rcvr) | ||
} else { | ||
err = srv.Register(rcvr) | ||
} | ||
if err != nil { | ||
return err | ||
} | ||
mux := http.NewServeMux() | ||
mux.Handle("/rpc", jsonrpc2.HTTPHandler(srv)) | ||
return HTTP(ctx, addr, tlsConfig, mux, "JSON-RPC 2.0") | ||
} |