rpc-go/registry/rpc-registry.go

189 lines
5.3 KiB
Go
Raw Permalink Normal View History

2018-04-03 08:58:26 +00:00
package registry
import (
"reflect"
"git.loafle.net/commons/rpc-go/protocol"
2018-04-10 09:02:35 +00:00
cus "git.loafle.net/commons/util-go/service"
2018-04-03 08:58:26 +00:00
)
// NewRPCRegistry returns a new RPC registry.
func NewRPCRegistry() RPCRegistry {
return &rpcRegistry{
2018-04-10 09:02:35 +00:00
serviceRegistry: new(cus.ServiceRegistry),
2018-04-03 08:58:26 +00:00
}
}
type RPCRegistry interface {
RPCInvoker
GetService(name string) interface{}
RegisterService(receiver interface{}, name string) error
2018-04-05 04:02:04 +00:00
RegisterServices(receivers ...interface{}) error
RegisterServiceMap(keysAndValues map[string]interface{}) error
2018-04-03 08:58:26 +00:00
}
// RPCRegistry serves registered RPC services using registered codecs.
type rpcRegistry struct {
2018-04-10 09:02:35 +00:00
serviceRegistry *cus.ServiceRegistry
2018-04-03 08:58:26 +00:00
}
// RegisterService adds a new service to the server.
//
// The name parameter is optional: if empty it will be inferred from
// the receiver type name.
//
// Methods from the receiver will be extracted if these rules are satisfied:
//
// - The receiver is exported (begins with an upper case letter) or local
// (defined in the package registering the service).
// - The method name is exported.
// - The method has two arguments: *args, *reply.
// - All two arguments are pointers.
// - The first and second arguments are exported or local.
// - The method has return type error.
//
// All other methods are ignored.
func (rr *rpcRegistry) RegisterService(receiver interface{}, name string) error {
2018-04-10 09:02:35 +00:00
return rr.serviceRegistry.Register(receiver, name)
2018-04-03 08:58:26 +00:00
}
2018-04-05 04:02:04 +00:00
func (rr *rpcRegistry) RegisterServices(receivers ...interface{}) error {
if nil == receivers || 0 == len(receivers) {
return nil
}
for _, receiver := range receivers {
2018-04-10 09:02:35 +00:00
if err := rr.serviceRegistry.Register(receiver, ""); nil != err {
2018-04-05 04:02:04 +00:00
return err
}
}
return nil
}
func (rr *rpcRegistry) RegisterServiceMap(keysAndValues map[string]interface{}) error {
if nil == keysAndValues || 0 == len(keysAndValues) {
return nil
}
for name, receiver := range keysAndValues {
2018-04-10 09:02:35 +00:00
if err := rr.serviceRegistry.Register(receiver, name); nil != err {
2018-04-05 04:02:04 +00:00
return err
}
}
return nil
}
2018-04-03 08:58:26 +00:00
func (rr *rpcRegistry) GetService(name string) interface{} {
2018-04-10 09:02:35 +00:00
return rr.serviceRegistry.GetService(name)
2018-04-03 08:58:26 +00:00
}
// HasMethod returns true if the given method is registered.
//
// The method uses a dotted notation as in "Service.Method".
func (rr *rpcRegistry) HasMethod(method string) bool {
2018-04-10 09:02:35 +00:00
if _, _, err := rr.serviceRegistry.Get(method); err == nil {
2018-04-03 08:58:26 +00:00
return true
}
return false
}
// Invoke execute a method.
//
// Codecs are defined to process a given serialization scheme, e.g., JSON or
// XML. A codec is chosen based on the "Content-Type" header from the request,
// excluding the charset definition.
2018-04-06 07:50:10 +00:00
func (rr *rpcRegistry) Invoke(codec protocol.RegistryCodec, leadingParams ...interface{}) (result interface{}, err error) {
2018-04-10 09:02:35 +00:00
serviceSpec, methodSpec, errGet := rr.serviceRegistry.Get(codec.Method())
2018-04-05 01:12:33 +00:00
if nil != errGet {
2018-04-03 08:58:26 +00:00
return nil, errGet
}
// Decode the args.
var in []reflect.Value
2018-04-10 09:02:35 +00:00
pValues, pInstances := methodSpec.ParamValues()
2018-04-11 05:53:49 +00:00
lParamLen := 0
2018-04-06 10:04:59 +00:00
if nil != leadingParams {
lParamLen = len(leadingParams)
}
2018-04-03 08:58:26 +00:00
if nil != pInstances && 0 < len(pInstances) {
2018-04-06 10:04:59 +00:00
if errRead := codec.ReadParams(pInstances[lParamLen:]); errRead != nil {
2018-04-03 08:58:26 +00:00
return nil, errRead
}
2018-04-06 10:04:59 +00:00
2018-04-03 08:58:26 +00:00
pCount := len(pInstances)
in = make([]reflect.Value, pCount+1)
2018-04-06 10:04:59 +00:00
2018-04-11 05:53:49 +00:00
for indexI := lParamLen; indexI < pCount; indexI++ {
2018-04-03 08:58:26 +00:00
if pValues[indexI].Type().Kind() == reflect.Ptr && pValues[indexI].Type().Elem().Kind() != reflect.Struct {
in[indexI+1] = reflect.Indirect(pValues[indexI])
} else {
in[indexI+1] = pValues[indexI]
}
}
} else {
in = make([]reflect.Value, 1)
}
2018-04-10 09:02:35 +00:00
in[0] = serviceSpec.ReceiverValue()
2018-04-03 08:58:26 +00:00
2018-04-11 05:53:49 +00:00
for indexI := 0; indexI < lParamLen; indexI++ {
in[indexI+1] = reflect.ValueOf(leadingParams[indexI])
}
2018-04-03 08:58:26 +00:00
// Call the service method.
2018-04-10 09:02:35 +00:00
returnValues := methodSpec.Call(in)
2018-04-03 08:58:26 +00:00
2018-04-10 09:02:35 +00:00
if nil != methodSpec.ReturnType() {
2018-04-03 08:58:26 +00:00
result = returnValues[0].Interface()
if nil != returnValues[1].Interface() {
err = returnValues[1].Interface().(error)
}
} else {
if nil != returnValues[0].Interface() {
err = returnValues[0].Interface().(error)
}
}
return
}
// func convertValues(values []interface{}, types []reflect.Type) []reflect.Value {
// c := len(values)
// vs := make([]reflect.Value, c)
// for indexI := 0; indexI < c; indexI++ {
// vs[indexI] = convertValue(&values[indexI], types[indexI])
// }
// return vs
// }
// func convertValue(v *interface{}, t reflect.Type) reflect.Value {
// switch t.Kind() {
// case reflect.Bool:
// return reflect.ValueOf(*v).Convert(t)
// case reflect.Float32, reflect.Float64:
// return reflect.ValueOf(*v).Convert(t)
// case reflect.Int, reflect.Int32, reflect.Int64:
// return reflect.ValueOf(*v).Convert(t)
// case reflect.Interface:
// // When we see an interface, we make our own thing
// return reflect.ValueOf(*v).Convert(t)
// case reflect.Map:
// return reflect.ValueOf(*v).M
// return d.decodeMap(name, node, result)
// case reflect.Ptr:
// return d.decodePtr(name, node, result)
// case reflect.Slice:
// return d.decodeSlice(name, node, result)
// case reflect.String:
// return d.decodeString(name, node, result)
// case reflect.Struct:
// return d.decodeStruct(name, node, result)
// default:
// return &parser.PosError{
// Pos: node.Pos(),
// Err: fmt.Errorf("%s: unknown kind to decode into: %s", name, k.Kind()),
// }
// }
// }