Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/3.0' into lumberjack_log
Browse files Browse the repository at this point in the history
  • Loading branch information
cjphaha committed Jul 26, 2021
2 parents 001221d + 9aeb7ff commit a472476
Show file tree
Hide file tree
Showing 22 changed files with 1,652 additions and 487 deletions.
8 changes: 0 additions & 8 deletions common/constant/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,3 @@ const (
DEFAULT_LOG_CONF_FILE_PATH = "../profiles/dev/log.yml"
DEFAULT_ROUTER_CONF_FILE_PATH = "../profiles/dev/router.yml"
)

// default config value
const (
DEFAULT_REGISTRY_ZK_ID = "demoZK"
DEFAULT_REGISTRY_ZK_PROTOCOL = ZOOKEEPER_KEY
DEFAULT_REGISTRY_ZK_TIMEOUT = "3s"
DEFAULT_REGISTRY_ZK_ADDRESS = "127.0.0.1:2181"
)
8 changes: 8 additions & 0 deletions common/constant/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,3 +307,11 @@ const (
// SERVICE_DISCOVERY_KEY indicate which service discovery instance will be used
SERVICE_DISCOVERY_KEY = "service_discovery"
)

// Generic Filter

const (
GenericSerializationDefault = "true"
// disable "protobuf-json" temporarily
//GenericSerializationProtobuf = "protobuf-json"
)
File renamed without changes.
2 changes: 1 addition & 1 deletion common/rpc_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ func suiteMethod(method reflect.Method) *MethodType {

// The latest return type of the method must be error.
if returnType := mtype.Out(outNum - 1); returnType != typeOfError {
logger.Warnf("the latest return type %s of method %q is not error", returnType, mname)
logger.Debugf(`"%s" method will not be exported because its last return type %v doesn't have error`, mname, returnType)
return nil
}

Expand Down
13 changes: 1 addition & 12 deletions config/config_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,9 @@ func DefaultInit() []LoaderInitOption {

// setDefaultValue set default value for providerConfig or consumerConfig if it is null
func setDefaultValue(target interface{}) {
registryConfig := &RegistryConfig{
Protocol: constant.DEFAULT_REGISTRY_ZK_PROTOCOL,
TimeoutStr: constant.DEFAULT_REGISTRY_ZK_TIMEOUT,
Address: constant.DEFAULT_REGISTRY_ZK_ADDRESS,
}
switch target.(type) {
case *ProviderConfig:
p := target.(*ProviderConfig)
if len(p.Registries) == 0 && p.Registry == nil {
p.Registries[constant.DEFAULT_REGISTRY_ZK_ID] = registryConfig
}
if len(p.Protocols) == 0 {
p.Protocols[constant.DEFAULT_PROTOCOL] = &ProtocolConfig{
Name: constant.DEFAULT_PROTOCOL,
Expand All @@ -117,9 +109,6 @@ func setDefaultValue(target interface{}) {
}
default:
c := target.(*ConsumerConfig)
if len(c.Registries) == 0 && c.Registry == nil {
c.Registries[constant.DEFAULT_REGISTRY_ZK_ID] = registryConfig
}
if c.ApplicationConfig == nil {
c.ApplicationConfig = NewDefaultApplicationConfig()
}
Expand Down Expand Up @@ -171,7 +160,7 @@ func loadConsumerConfig() {

checkRegistries(consumerConfig.Registries, consumerConfig.Registry)
for key, ref := range consumerConfig.References {
if ref.Generic {
if ref.Generic != "" {
genericService := NewGenericService(key)
SetConsumerService(genericService)
}
Expand Down
6 changes: 0 additions & 6 deletions config/config_loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,19 +207,13 @@ func TestSetDefaultValue(t *testing.T) {
proConfig := &ProviderConfig{Registries: make(map[string]*RegistryConfig), Protocols: make(map[string]*ProtocolConfig)}
assert.Nil(t, proConfig.ApplicationConfig)
setDefaultValue(proConfig)
assert.Equal(t, proConfig.Registries["demoZK"].Address, "127.0.0.1:2181")
assert.Equal(t, proConfig.Registries["demoZK"].TimeoutStr, "3s")
assert.Equal(t, proConfig.Registries["demoZK"].Protocol, "zookeeper")
assert.Equal(t, proConfig.Protocols["dubbo"].Name, "dubbo")
assert.Equal(t, proConfig.Protocols["dubbo"].Port, "20000")
assert.NotNil(t, proConfig.ApplicationConfig)

conConfig := &ConsumerConfig{Registries: make(map[string]*RegistryConfig)}
assert.Nil(t, conConfig.ApplicationConfig)
setDefaultValue(conConfig)
assert.Equal(t, conConfig.Registries["demoZK"].Address, "127.0.0.1:2181")
assert.Equal(t, conConfig.Registries["demoZK"].TimeoutStr, "3s")
assert.Equal(t, conConfig.Registries["demoZK"].Protocol, "zookeeper")
assert.NotNil(t, conConfig.ApplicationConfig)

}
Expand Down
10 changes: 5 additions & 5 deletions config/reference_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ type ReferenceConfig struct {
Params map[string]string `yaml:"params" json:"params,omitempty" property:"params"`
invoker protocol.Invoker
urls []*common.URL
Generic bool `yaml:"generic" json:"generic,omitempty" property:"generic"`
Generic string `yaml:"generic" json:"generic,omitempty" property:"generic"`
Sticky bool `yaml:"sticky" json:"sticky,omitempty" property:"sticky"`
RequestTimeout string `yaml:"timeout" json:"timeout,omitempty" property:"timeout"`
ForceTag bool `yaml:"force.tag" json:"force.tag,omitempty" property:"force.tag"`
Expand Down Expand Up @@ -133,9 +133,9 @@ func (c *ReferenceConfig) Refer(_ interface{}) {

if len(c.urls) == 1 {
c.invoker = extension.GetProtocol(c.urls[0].Protocol).Refer(c.urls[0])
// c.URL != "" is direct call
// c.URL != "" is direct call, and will overide c.invoker
if c.URL != "" {
//filter
// filter
c.invoker = protocolwrapper.BuildInvokerChain(c.invoker, constant.REFERENCE_FILTER_KEY)

// cluster
Expand Down Expand Up @@ -236,7 +236,7 @@ func (c *ReferenceConfig) getURLMap() url.Values {
urlMap.Set(constant.RETRIES_KEY, c.Retries)
urlMap.Set(constant.GROUP_KEY, c.Group)
urlMap.Set(constant.VERSION_KEY, c.Version)
urlMap.Set(constant.GENERIC_KEY, strconv.FormatBool(c.Generic))
urlMap.Set(constant.GENERIC_KEY, c.Generic)
urlMap.Set(constant.ROLE_KEY, strconv.Itoa(common.CONSUMER))
urlMap.Set(constant.PROVIDED_BY, c.ProvidedBy)
urlMap.Set(constant.SERIALIZATION_KEY, c.Serialization)
Expand All @@ -262,7 +262,7 @@ func (c *ReferenceConfig) getURLMap() url.Values {

// filter
defaultReferenceFilter := constant.DEFAULT_REFERENCE_FILTERS
if c.Generic {
if c.Generic != "" {
defaultReferenceFilter = constant.GENERIC_REFERENCE_FILTERS + "," + defaultReferenceFilter
}
urlMap.Set(constant.REFERENCE_FILTER_KEY, mergeValue(consumerConfig.Filter, c.Filter, defaultReferenceFilter))
Expand Down
139 changes: 39 additions & 100 deletions filter/generic/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ package generic

import (
"context"
"reflect"
"strings"
"time"
)

import (
Expand All @@ -31,6 +28,7 @@ import (
import (
"dubbo.apache.org/dubbo-go/v3/common/constant"
"dubbo.apache.org/dubbo-go/v3/common/extension"
"dubbo.apache.org/dubbo-go/v3/common/logger"
"dubbo.apache.org/dubbo-go/v3/filter"
"dubbo.apache.org/dubbo-go/v3/protocol"
invocation2 "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
Expand All @@ -42,30 +40,52 @@ func init() {
})
}

// when do a generic invoke, struct need to be map

// nolint
// Filter ensures the structs are converted to maps, this filter is for consumer
type Filter struct{}

// Invoke turns the parameters to map for generic method
func (f *Filter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
if invocation.MethodName() == constant.GENERIC && len(invocation.Arguments()) == 3 {
oldArguments := invocation.Arguments()
if isCallingToGenericService(invoker, invocation) {

mtdname := invocation.MethodName()
oldargs := invocation.Arguments()

types := make([]string, 0, len(oldargs))
args := make([]hessian.Object, 0, len(oldargs))

if oldParams, ok := oldArguments[2].([]interface{}); ok {
newParams := make([]hessian.Object, 0, len(oldParams))
for i := range oldParams {
newParams = append(newParams, hessian.Object(struct2MapAll(oldParams[i])))
// get generic info from attachments of invocation, the default value is "true"
generic := invocation.AttachmentsByKey(constant.GENERIC_KEY, constant.GenericSerializationDefault)
// get generalizer according to value in the `generic`
g := getGeneralizer(generic)

for _, arg := range oldargs {
// use the default generalizer(MapGeneralizer)
typ, err := g.GetType(arg)
if err != nil {
logger.Errorf("failed to get type, %v", err)
}
newArguments := []interface{}{
oldArguments[0],
oldArguments[1],
newParams,
obj, err := g.Generalize(arg)
if err != nil {
logger.Errorf("generalization failed, %v", err)
return invoker.Invoke(ctx, invocation)
}
newInvocation := invocation2.NewRPCInvocation(invocation.MethodName(), newArguments, invocation.Attachments())
newInvocation.SetReply(invocation.Reply())
return invoker.Invoke(ctx, newInvocation)
types = append(types, typ)
args = append(args, obj)
}

// construct a new invocation for generic call
newargs := []interface{}{
mtdname,
types,
args,
}
newivc := invocation2.NewRPCInvocation(constant.GENERIC, newargs, invocation.Attachments())
newivc.SetReply(invocation.Reply())
newivc.Attachments()[constant.GENERIC_KEY] = invoker.GetURL().GetParam(constant.GENERIC_KEY, "")

return invoker.Invoke(ctx, newivc)
} else if isMakingAGenericCall(invoker, invocation) {
invocation.Attachments()[constant.GENERIC_KEY] = invoker.GetURL().GetParam(constant.GENERIC_KEY, "")
}
return invoker.Invoke(ctx, invocation)
}
Expand All @@ -75,84 +95,3 @@ func (f *Filter) OnResponse(_ context.Context, result protocol.Result, _ protoco
_ protocol.Invocation) protocol.Result {
return result
}

func struct2MapAll(obj interface{}) interface{} {
if obj == nil {
return obj
}
t := reflect.TypeOf(obj)
v := reflect.ValueOf(obj)
if t.Kind() == reflect.Struct {
result := make(map[string]interface{}, t.NumField())
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
kind := value.Kind()
if kind == reflect.Struct || kind == reflect.Slice || kind == reflect.Map {
if value.CanInterface() {
tmp := value.Interface()
if _, ok := tmp.(time.Time); ok {
setInMap(result, field, tmp)
continue
}
setInMap(result, field, struct2MapAll(tmp))
}
} else {
if value.CanInterface() {
setInMap(result, field, value.Interface())
}
}
}
return result
} else if t.Kind() == reflect.Slice {
value := reflect.ValueOf(obj)
newTemps := make([]interface{}, 0, value.Len())
for i := 0; i < value.Len(); i++ {
newTemp := struct2MapAll(value.Index(i).Interface())
newTemps = append(newTemps, newTemp)
}
return newTemps
} else if t.Kind() == reflect.Map {
newTempMap := make(map[interface{}]interface{}, v.Len())
iter := v.MapRange()
for iter.Next() {
if !iter.Value().CanInterface() {
continue
}
key := iter.Key()
mapV := iter.Value().Interface()
newTempMap[convertMapKey(key)] = struct2MapAll(mapV)
}
return newTempMap
} else {
return obj
}
}

func convertMapKey(key reflect.Value) interface{} {
switch key.Kind() {
case reflect.Bool, reflect.Int, reflect.Int8,
reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16,
reflect.Uint32, reflect.Uint64, reflect.Float32,
reflect.Float64, reflect.String:
return key.Interface()
default:
return key.String()
}
}

func setInMap(m map[string]interface{}, structField reflect.StructField, value interface{}) (result map[string]interface{}) {
result = m
if tagName := structField.Tag.Get("m"); tagName == "" {
result[headerAtoa(structField.Name)] = value
} else {
result[tagName] = value
}
return
}

func headerAtoa(a string) (b string) {
b = strings.ToLower(a[:1]) + a[1:]
return
}
Loading

0 comments on commit a472476

Please sign in to comment.