88 lines
2.4 KiB
Go
88 lines
2.4 KiB
Go
package rpcx
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"go_dreamfactory/lego/sys/log"
|
|
"reflect"
|
|
"runtime"
|
|
"sync"
|
|
)
|
|
|
|
var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
|
|
var typeOfContext = reflect.TypeOf((*context.Context)(nil)).Elem()
|
|
|
|
type seqKey struct{}
|
|
type methodType struct {
|
|
sync.Mutex // protects counters
|
|
method reflect.Method
|
|
ArgType reflect.Type
|
|
ReplyType reflect.Type
|
|
// numCalls uint
|
|
}
|
|
|
|
type functionType struct {
|
|
sync.Mutex // protects counters
|
|
fn reflect.Value
|
|
ArgType reflect.Type
|
|
ReplyType reflect.Type
|
|
}
|
|
|
|
type service struct {
|
|
name string // name of service
|
|
rcvr reflect.Value // receiver of methods for the service
|
|
typ reflect.Type // type of the receiver
|
|
method map[string]*methodType // registered methods
|
|
function map[string]*functionType // registered functions
|
|
}
|
|
|
|
func (this *service) call(ctx context.Context, mtype *methodType, argv, replyv reflect.Value) (err error) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
buf := make([]byte, 4096)
|
|
n := runtime.Stack(buf, false)
|
|
buf = buf[:n]
|
|
|
|
err = fmt.Errorf("[service internal error]: %v, method: %s, argv: %+v, stack: %s",
|
|
r, mtype.method.Name, argv.Interface(), buf)
|
|
log.Errorf("err%v", err)
|
|
}
|
|
}()
|
|
|
|
function := mtype.method.Func
|
|
// Invoke the method, providing a new value for the reply.
|
|
returnValues := function.Call([]reflect.Value{this.rcvr, reflect.ValueOf(ctx), argv, replyv})
|
|
// The return value for the method is an error.
|
|
errInter := returnValues[0].Interface()
|
|
if errInter != nil {
|
|
return errInter.(error)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
//执行注册方法
|
|
func (this *service) callForFunction(ctx context.Context, ft *functionType, argv, replyv reflect.Value) (err error) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
buf := make([]byte, 4096)
|
|
n := runtime.Stack(buf, false)
|
|
buf = buf[:n]
|
|
|
|
// log.Errorf("failed to invoke service: %v, stacks: %s", r, string(debug.Stack()))
|
|
err = fmt.Errorf("[service internal error]: %v, function: %s, argv: %+v, stack: %s",
|
|
r, runtime.FuncForPC(ft.fn.Pointer()), argv.Interface(), buf)
|
|
log.Errorf("err:%v", err)
|
|
}
|
|
}()
|
|
|
|
// Invoke the function, providing a new value for the reply.
|
|
returnValues := ft.fn.Call([]reflect.Value{reflect.ValueOf(ctx), argv, replyv})
|
|
// The return value for the method is an error.
|
|
errInter := returnValues[0].Interface()
|
|
if errInter != nil {
|
|
return errInter.(error)
|
|
}
|
|
|
|
return nil
|
|
}
|