Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Imp: some improvements #98

Merged
merged 13 commits into from
Jun 19, 2019
5 changes: 4 additions & 1 deletion common/constant/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const (
DEFAULT_LOADBALANCE = "random"
DEFAULT_RETRIES = 2
DEFAULT_PROTOCOL = "dubbo"
DEFAULT_VERSION = ""
DEFAULT_REG_TIMEOUT = "10s"
DEFAULT_CLUSTER = "failover"
)
Expand All @@ -37,3 +36,7 @@ const (
DEFAULT_REFERENCE_FILTERS = ""
ECHO = "$echo"
)

const (
ANY_VALUE = "*"
)
1 change: 1 addition & 0 deletions common/constant/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const (
WEIGHT_KEY = "weight"
WARMUP_KEY = "warmup"
RETRIES_KEY = "retries"
BEAN_NAME = "bean.name"
)

const (
Expand Down
4 changes: 2 additions & 2 deletions common/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func init() {
logConfFile := os.Getenv(constant.APP_LOG_CONF_FILE)
err := InitLog(logConfFile)
if err != nil {
log.Printf("[InitLog] error: %v", err)
log.Printf("[InitLog] warn: %v", err)
}
}

Expand Down Expand Up @@ -110,7 +110,7 @@ func InitLogger(conf *zap.Config) {
} else {
zapLoggerConfig = *conf
}
zapLogger, _ := zapLoggerConfig.Build()
zapLogger, _ := zapLoggerConfig.Build(zap.AddCallerSkip(1))
logger = zapLogger.Sugar()
}

Expand Down
42 changes: 24 additions & 18 deletions common/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package proxy

import (
"reflect"
"sync"
)

import (
Expand All @@ -34,6 +35,8 @@ type Proxy struct {
invoke protocol.Invoker
callBack interface{}
attachments map[string]string

once sync.Once
}

var typError = reflect.Zero(reflect.TypeOf((*error)(nil)).Elem()).Type()
Expand Down Expand Up @@ -78,23 +81,31 @@ func (p *Proxy) Implement(v common.RPCService) {
methodName = "$echo"
}

start := 0
end := len(in)
if in[0].Type().String() == "context.Context" {
start += 1
}
if len(outs) == 1 {
end -= 1
reply = in[len(in)-1]
} else {
if len(outs) == 2 {
if outs[0].Kind() == reflect.Ptr {
reply = reflect.New(outs[0].Elem())
} else {
reply = reflect.New(outs[0])
}
} else {
reply = valueOf
}

start := 0
end := len(in)
if end > 0 {
if in[0].Type().String() == "context.Context" {
start += 1
}
if len(outs) == 1 && in[end-1].Type().Kind() == reflect.Ptr {
end -= 1
reply = in[len(in)-1]
}
}

if v, ok := in[start].Interface().([]interface{}); ok && end-start == 1 {
if end-start <= 0 {
inArr = []interface{}{}
} else if v, ok := in[start].Interface().([]interface{}); ok && end-start == 1 {
inArr = v
} else {
inArr = make([]interface{}, end-start)
Expand Down Expand Up @@ -134,7 +145,6 @@ func (p *Proxy) Implement(v common.RPCService) {
}
f := valueOfElem.Field(i)
if f.Kind() == reflect.Func && f.IsValid() && f.CanSet() {
inNum := t.Type.NumIn()
outNum := t.Type.NumOut()

if outNum != 1 && outNum != 2 {
Expand All @@ -149,12 +159,6 @@ func (p *Proxy) Implement(v common.RPCService) {
continue
}

// reply must be Ptr when outNum == 1
if outNum == 1 && t.Type.In(inNum-1).Kind() != reflect.Ptr {
logger.Warnf("reply type of method %q is not a pointer", t.Name)
continue
}

var funcOuts = make([]reflect.Type, outNum)
for i := 0; i < outNum; i++ {
funcOuts[i] = t.Type.Out(i)
Expand All @@ -166,7 +170,9 @@ func (p *Proxy) Implement(v common.RPCService) {
}
}

p.rpc = v
p.once.Do(func() {
p.rpc = v
})

}

Expand Down
2 changes: 1 addition & 1 deletion common/proxy/proxy_factory/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ func (factory *DefaultProxyFactory) GetProxy(invoker protocol.Invoker, url *comm
return proxy.NewProxy(invoker, nil, attachments)
}
func (factory *DefaultProxyFactory) GetInvoker(url common.URL) protocol.Invoker {
//TODO:yincheng need to do the service invoker refactor
// todo: call service
return protocol.NewBaseInvoker(url)
}
9 changes: 6 additions & 3 deletions common/proxy/proxy_factory/default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,25 @@ import (
"testing"
)

import (
"github.com/stretchr/testify/assert"
)

import (
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/protocol"
"github.com/stretchr/testify/assert"
)

func Test_GetProxy(t *testing.T) {
proxyFactory := NewDefaultProxyFactory()
url := common.NewURLWithOptions("testservice")
url := common.NewURLWithOptions()
proxy := proxyFactory.GetProxy(protocol.NewBaseInvoker(*url), url)
assert.NotNil(t, proxy)
}

func Test_GetInvoker(t *testing.T) {
proxyFactory := NewDefaultProxyFactory()
url := common.NewURLWithOptions("testservice")
url := common.NewURLWithOptions()
invoker := proxyFactory.GetInvoker(*url)
assert.True(t, invoker.IsAvailable())
}
25 changes: 11 additions & 14 deletions common/proxy/proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ import (

type TestService struct {
MethodOne func(context.Context, int, bool, *interface{}) error
MethodTwo func([]interface{}, *interface{}) error
MethodTwo func([]interface{}) error
MethodThree func(int, bool) (interface{}, error)
MethodFour func(int, bool) (*interface{}, error) `dubbo:"methodFour"`
MethodFive func() error
Echo func(interface{}, *interface{}) error
}

Expand All @@ -64,19 +65,25 @@ func TestProxy_Implement(t *testing.T) {
p := NewProxy(invoker, nil, map[string]string{constant.ASYNC_KEY: "false"})
s := &TestService{}
p.Implement(s)

err := p.Get().(*TestService).MethodOne(nil, 0, false, nil)
assert.NoError(t, err)
err = p.Get().(*TestService).MethodTwo(nil, nil)

err = p.Get().(*TestService).MethodTwo(nil)
assert.NoError(t, err)
ret, err := p.Get().(*TestService).MethodThree(0, false)
assert.NoError(t, err)
assert.Nil(t, ret) // ret is nil, because it doesn't be injection yet

ret2, err := p.Get().(*TestService).MethodFour(0, false)
assert.NoError(t, err)
assert.Equal(t, "*interface {}", reflect.TypeOf(ret2).String())
err = p.Get().(*TestService).Echo(nil, nil)
assert.NoError(t, err)

err = p.Get().(*TestService).MethodFive()
assert.NoError(t, err)

// inherit & lowercase
p.rpc = nil
type S1 struct {
Expand Down Expand Up @@ -108,24 +115,14 @@ func TestProxy_Implement(t *testing.T) {
p.Implement(s2)
assert.Nil(t, s2.MethodOne)

// reply type
// returns type
p.rpc = nil
type S3 struct {
TestService
MethodOne func(context.Context, []interface{}, struct{}) error
MethodOne func(context.Context, []interface{}, *struct{}) interface{}
}
s3 := &S3{TestService: *s}
p.Implement(s3)
assert.Nil(t, s3.MethodOne)

// returns type
p.rpc = nil
type S4 struct {
TestService
MethodOne func(context.Context, []interface{}, *struct{}) interface{}
}
s4 := &S4{TestService: *s}
p.Implement(s4)
assert.Nil(t, s4.MethodOne)

}
37 changes: 22 additions & 15 deletions common/rpc_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ type RPCService interface {
Version() string
}

// for lowercase func
// func MethodMapper() map[string][string] {
// return map[string][string]{}
// }
const METHOD_MAPPER = "MethodMapper"

var (
// Precompute the reflect type for error. Can't use error directly
// because Typeof takes an empty interface value. This is annoying.
Expand Down Expand Up @@ -210,20 +216,26 @@ func isExportedOrBuiltinType(t reflect.Type) bool {
// suitableMethods returns suitable Rpc methods of typ
func suitableMethods(typ reflect.Type) (string, map[string]*MethodType) {
methods := make(map[string]*MethodType)
mts := ""
var mts []string
logger.Debugf("[%s] NumMethod is %d", typ.String(), typ.NumMethod())
method, ok := typ.MethodByName(METHOD_MAPPER)
var methodMapper map[string]string
if ok && method.Type.NumIn() == 1 && method.Type.NumOut() == 1 && method.Type.Out(0).String() == "map[string]string" {
methodMapper = method.Func.Call([]reflect.Value{reflect.New(typ.Elem())})[0].Interface().(map[string]string)
}

for m := 0; m < typ.NumMethod(); m++ {
method := typ.Method(m)
method = typ.Method(m)
if mt := suiteMethod(method); mt != nil {
methods[method.Name] = mt
if m == 0 {
mts += method.Name
} else {
mts += "," + method.Name
methodName, ok := methodMapper[method.Name]
if !ok {
methodName = method.Name
}
methods[methodName] = mt
mts = append(mts, methodName)
}
}
return mts, methods
return strings.Join(mts, ","), methods
}

// suiteMethod returns a suitable Rpc methodType
Expand Down Expand Up @@ -256,12 +268,7 @@ func suiteMethod(method reflect.Method) *MethodType {
}

// replyType
if outNum == 1 {
if mtype.In(inNum-1).Kind() != reflect.Ptr {
logger.Errorf("reply type of method %q is not a pointer %v", mname, replyType)
return nil
}
} else {
if outNum == 2 {
replyType = mtype.Out(0)
if !isExportedOrBuiltinType(replyType) {
logger.Errorf("reply type of method %s not exported{%v}", mname, replyType)
Expand All @@ -272,7 +279,7 @@ func suiteMethod(method reflect.Method) *MethodType {
index := 1

// ctxType
if mtype.In(1).String() == "context.Context" {
if inNum > 1 && mtype.In(1).String() == "context.Context" {
ctxType = mtype.In(1)
index = 2
}
Expand Down
Loading