go_dreamfactory/lego/sys/rpcx/utils.go
2022-06-17 17:32:25 +08:00

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
}