DMwangnima commented on code in PR #2502: URL: https://github.com/apache/dubbo-go/pull/2502#discussion_r1392775466
########## common/dubboutil/copier.go: ########## @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dubboutil + +import ( + "reflect" +) + +func CopyFields(sourceValue reflect.Value, targetValue reflect.Value) { Review Comment: Java-Style but very efficient code :) ########## client/options.go: ########## @@ -131,239 +130,542 @@ func (cliOpts *ClientOptions) init(opts ...ClientOption) error { ref.RegistryIDs = commonCfg.TranslateIds(ref.RegistryIDs) // init graceful_shutdown - graceful_shutdown.Init(graceful_shutdown.SetShutdown_Config(cliOpts.Shutdown)) + graceful_shutdown.Init(graceful_shutdown.SetShutdown_Config(refOpts.cliOpts.Shutdown)) - return commonCfg.Verify(cliOpts) + return commonCfg.Verify(refOpts) } -type ClientOption func(*ClientOptions) +type ReferenceOption func(*ReferenceOptions) // ---------- For user ---------- -func WithCheck() ClientOption { - return func(opts *ClientOptions) { +func WithCheck() ReferenceOption { + return func(opts *ReferenceOptions) { check := true opts.Reference.Check = &check } } -func WithURL(url string) ClientOption { - return func(opts *ClientOptions) { +func WithURL(url string) ReferenceOption { + return func(opts *ReferenceOptions) { opts.Reference.URL = url } } // todo(DMwangnima): change Filter Option like Cluster and LoadBalance -func WithFilter(filter string) ClientOption { - return func(opts *ClientOptions) { +func WithFilter(filter string) ReferenceOption { + return func(opts *ReferenceOptions) { opts.Reference.Filter = filter } } // todo(DMwangnima): think about a more ideal configuration style -func WithRegistryIDs(registryIDs []string) ClientOption { - return func(opts *ClientOptions) { +func WithRegistryIDs(registryIDs []string) ReferenceOption { + return func(opts *ReferenceOptions) { if len(registryIDs) > 0 { opts.Reference.RegistryIDs = registryIDs } } } -func WithRegistry(opts ...registry.Option) ClientOption { +func WithRegistry(opts ...registry.Option) ReferenceOption { regOpts := registry.NewOptions(opts...) - return func(cliOpts *ClientOptions) { - if cliOpts.Registries == nil { - cliOpts.Registries = make(map[string]*global.RegistryConfig) + return func(refOpts *ReferenceOptions) { + if refOpts.Registries == nil { + refOpts.Registries = make(map[string]*global.RegistryConfig) } - cliOpts.Registries[regOpts.ID] = regOpts.Registry + refOpts.Registries[regOpts.ID] = regOpts.Registry + } +} + +// ========== Cluster Strategy ========== + +func WithClusterAvailable() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyAvailable + } +} + +func WithClusterBroadcast() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyBroadcast + } +} + +func WithClusterFailBack() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyFailback + } +} + +func WithClusterFailFast() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyFailfast + } +} + +func WithClusterFailOver() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyFailover + } +} + +func WithClusterFailSafe() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyFailsafe + } +} + +func WithClusterForking() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyForking + } +} + +func WithClusterZoneAware() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyZoneAware + } +} + +func WithClusterAdaptiveService() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyAdaptiveService + } +} + +// ========== LoadBalance Strategy ========== + +func WithLoadBalanceConsistentHashing() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Loadbalance = constant.LoadBalanceKeyConsistentHashing } } -func WithShutdown(opts ...graceful_shutdown.Option) ClientOption { - sdOpts := graceful_shutdown.NewOptions(opts...) +func WithLoadBalanceLeastActive() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Loadbalance = constant.LoadBalanceKeyLeastActive + } +} + +func WithLoadBalanceRandom() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Loadbalance = constant.LoadBalanceKeyRandom + } +} + +func WithLoadBalanceRoundRobin() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Loadbalance = constant.LoadBalanceKeyRoundRobin + } +} + +func WithLoadBalanceP2C() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Loadbalance = constant.LoadBalanceKeyP2C + } +} + +func WithLoadBalanceXDSRingHash() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Loadbalance = constant.LoadBalanceKeyLeastActive + } +} + +func WithRetries(retries int) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Retries = strconv.Itoa(retries) + } +} + +func WithGroup(group string) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Group = group + } +} + +func WithVersion(version string) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Version = version + } +} + +func WithJSON() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Serialization = constant.JSONSerialization + } +} + +func WithProvidedBy(providedBy string) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.ProvidedBy = providedBy + } +} + +// todo(DMwangnima): implement this functionality +//func WithAsync() ReferenceOption { +// return func(opts *ReferenceOptions) { +// opts.Reference.Async = true +// } +//} + +func WithParams(params map[string]string) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Params = params + } +} + +// todo(DMwangnima): implement this functionality +//func WithGeneric(generic bool) ReferenceOption { +// return func(opts *ReferenceOptions) { +// if generic { +// opts.Reference.Generic = "true" +// } else { +// opts.Reference.Generic = "false" +// } +// } +//} + +func WithSticky(sticky bool) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Sticky = sticky + } +} + +// ========== Protocol to consume ========== + +func WithProtocolDubbo() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Protocol = constant.Dubbo + } +} + +func WithProtocolTriple() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Protocol = "tri" + } +} + +func WithProtocolJsonRPC() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Protocol = "jsonrpc" + } +} + +func WithProtocol(protocol string) ReferenceOption { Review Comment: Since we have enumerated protocols that we support, maybe there is no need to expose this API? ########## client/options.go: ########## @@ -131,239 +130,542 @@ func (cliOpts *ClientOptions) init(opts ...ClientOption) error { ref.RegistryIDs = commonCfg.TranslateIds(ref.RegistryIDs) // init graceful_shutdown - graceful_shutdown.Init(graceful_shutdown.SetShutdown_Config(cliOpts.Shutdown)) + graceful_shutdown.Init(graceful_shutdown.SetShutdown_Config(refOpts.cliOpts.Shutdown)) - return commonCfg.Verify(cliOpts) + return commonCfg.Verify(refOpts) } -type ClientOption func(*ClientOptions) +type ReferenceOption func(*ReferenceOptions) // ---------- For user ---------- -func WithCheck() ClientOption { - return func(opts *ClientOptions) { +func WithCheck() ReferenceOption { + return func(opts *ReferenceOptions) { check := true opts.Reference.Check = &check } } -func WithURL(url string) ClientOption { - return func(opts *ClientOptions) { +func WithURL(url string) ReferenceOption { + return func(opts *ReferenceOptions) { opts.Reference.URL = url } } // todo(DMwangnima): change Filter Option like Cluster and LoadBalance -func WithFilter(filter string) ClientOption { - return func(opts *ClientOptions) { +func WithFilter(filter string) ReferenceOption { + return func(opts *ReferenceOptions) { opts.Reference.Filter = filter } } // todo(DMwangnima): think about a more ideal configuration style -func WithRegistryIDs(registryIDs []string) ClientOption { - return func(opts *ClientOptions) { +func WithRegistryIDs(registryIDs []string) ReferenceOption { + return func(opts *ReferenceOptions) { if len(registryIDs) > 0 { opts.Reference.RegistryIDs = registryIDs } } } -func WithRegistry(opts ...registry.Option) ClientOption { +func WithRegistry(opts ...registry.Option) ReferenceOption { regOpts := registry.NewOptions(opts...) - return func(cliOpts *ClientOptions) { - if cliOpts.Registries == nil { - cliOpts.Registries = make(map[string]*global.RegistryConfig) + return func(refOpts *ReferenceOptions) { + if refOpts.Registries == nil { + refOpts.Registries = make(map[string]*global.RegistryConfig) } - cliOpts.Registries[regOpts.ID] = regOpts.Registry + refOpts.Registries[regOpts.ID] = regOpts.Registry + } +} + +// ========== Cluster Strategy ========== + +func WithClusterAvailable() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyAvailable + } +} + +func WithClusterBroadcast() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyBroadcast + } +} + +func WithClusterFailBack() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyFailback + } +} + +func WithClusterFailFast() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyFailfast + } +} + +func WithClusterFailOver() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyFailover + } +} + +func WithClusterFailSafe() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyFailsafe + } +} + +func WithClusterForking() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyForking + } +} + +func WithClusterZoneAware() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyZoneAware + } +} + +func WithClusterAdaptiveService() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Cluster = constant.ClusterKeyAdaptiveService + } +} + +// ========== LoadBalance Strategy ========== + +func WithLoadBalanceConsistentHashing() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Loadbalance = constant.LoadBalanceKeyConsistentHashing } } -func WithShutdown(opts ...graceful_shutdown.Option) ClientOption { - sdOpts := graceful_shutdown.NewOptions(opts...) +func WithLoadBalanceLeastActive() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Loadbalance = constant.LoadBalanceKeyLeastActive + } +} + +func WithLoadBalanceRandom() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Loadbalance = constant.LoadBalanceKeyRandom + } +} + +func WithLoadBalanceRoundRobin() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Loadbalance = constant.LoadBalanceKeyRoundRobin + } +} + +func WithLoadBalanceP2C() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Loadbalance = constant.LoadBalanceKeyP2C + } +} + +func WithLoadBalanceXDSRingHash() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Loadbalance = constant.LoadBalanceKeyLeastActive + } +} + +func WithRetries(retries int) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Retries = strconv.Itoa(retries) + } +} + +func WithGroup(group string) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Group = group + } +} + +func WithVersion(version string) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Version = version + } +} + +func WithJSON() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Serialization = constant.JSONSerialization + } +} + +func WithProvidedBy(providedBy string) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.ProvidedBy = providedBy + } +} + +// todo(DMwangnima): implement this functionality +//func WithAsync() ReferenceOption { +// return func(opts *ReferenceOptions) { +// opts.Reference.Async = true +// } +//} + +func WithParams(params map[string]string) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Params = params + } +} + +// todo(DMwangnima): implement this functionality +//func WithGeneric(generic bool) ReferenceOption { +// return func(opts *ReferenceOptions) { +// if generic { +// opts.Reference.Generic = "true" +// } else { +// opts.Reference.Generic = "false" +// } +// } +//} + +func WithSticky(sticky bool) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Sticky = sticky + } +} + +// ========== Protocol to consume ========== + +func WithProtocolDubbo() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Protocol = constant.Dubbo + } +} + +func WithProtocolTriple() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Protocol = "tri" + } +} + +func WithProtocolJsonRPC() ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Protocol = "jsonrpc" + } +} + +func WithProtocol(protocol string) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.Protocol = protocol + } +} + +func WithRequestTimeout(timeout time.Duration) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.RequestTimeout = timeout.String() + } +} + +func WithForce(force bool) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.ForceTag = force + } +} + +func WithMeshProviderPort(port int) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference.MeshProviderPort = port + } +} + +// ---------- For framework ---------- +// These functions should not be invoked by users + +func SetRegistries(regs map[string]*global.RegistryConfig) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Registries = regs + } +} + +func SetReference(reference *global.ReferenceConfig) ReferenceOption { + return func(opts *ReferenceOptions) { + opts.Reference = reference + } +} + +type ClientOptions struct { + Consumer *global.ConsumerConfig + Application *global.ApplicationConfig + Registries map[string]*global.RegistryConfig + Shutdown *global.ShutdownConfig +} + +func defaultClientOptions() *ClientOptions { + return &ClientOptions{ + Consumer: global.DefaultConsumerConfig(), + Registries: make(map[string]*global.RegistryConfig), + Application: global.DefaultApplicationConfig(), + Shutdown: global.DefaultShutdownConfig(), + } +} + +func (cliOpts *ClientOptions) init(opts ...ClientOption) error { + for _, opt := range opts { + opt(cliOpts) + } + if err := defaults.Set(cliOpts); err != nil { + return err + } + return nil +} + +type ClientOption func(*ClientOptions) + +func WithClientCheck() ClientOption { + return func(opts *ClientOptions) { + opts.Consumer.Check = true + } +} + +func WithClientURL(url string) ClientOption { + return func(opts *ClientOptions) { + opts.Consumer.URL = url + } +} + +// todo(DMwangnima): change Filter Option like Cluster and LoadBalance +func WithClientFilter(filter string) ClientOption { + return func(opts *ClientOptions) { + opts.Consumer.Filter = filter + } +} + +// todo(DMwangnima): think about a more ideal configuration style +func WithClientRegistryIDs(registryIDs []string) ClientOption { + return func(opts *ClientOptions) { + if len(registryIDs) > 0 { + opts.Consumer.RegistryIDs = registryIDs + } + } +} + +func WithClientRegistry(opts ...registry.Option) ClientOption { + regOpts := registry.NewOptions(opts...) return func(cliOpts *ClientOptions) { - cliOpts.Shutdown = sdOpts.Shutdown + if cliOpts.Registries == nil { + cliOpts.Registries = make(map[string]*global.RegistryConfig) + } + cliOpts.Registries[regOpts.ID] = regOpts.Registry } } +//func WithClientShutdown(opts ...graceful_shutdown.Option) ClientOption { +// sdOpts := graceful_shutdown.NewOptions(opts...) +// +// return func(cliOpts *ClientOptions) { +// cliOpts.Shutdown = sdOpts.Shutdown +// } +//} + // ========== Cluster Strategy ========== -func WithClusterAvailable() ClientOption { +func WithClientClusterAvailable() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Cluster = constant.ClusterKeyAvailable + opts.Consumer.Cluster = constant.ClusterKeyAvailable } } -func WithClusterBroadcast() ClientOption { +func WithClientClusterBroadcast() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Cluster = constant.ClusterKeyBroadcast + opts.Consumer.Cluster = constant.ClusterKeyBroadcast } } -func WithClusterFailBack() ClientOption { +func WithClientClusterFailBack() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Cluster = constant.ClusterKeyFailback + opts.Consumer.Cluster = constant.ClusterKeyFailback } } -func WithClusterFailFast() ClientOption { +func WithClientClusterFailFast() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Cluster = constant.ClusterKeyFailfast + opts.Consumer.Cluster = constant.ClusterKeyFailfast } } -func WithClusterFailOver() ClientOption { +func WithClientClusterFailOver() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Cluster = constant.ClusterKeyFailover + opts.Consumer.Cluster = constant.ClusterKeyFailover } } -func WithClusterFailSafe() ClientOption { +func WithClientClusterFailSafe() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Cluster = constant.ClusterKeyFailsafe + opts.Consumer.Cluster = constant.ClusterKeyFailsafe } } -func WithClusterForking() ClientOption { +func WithClientClusterForking() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Cluster = constant.ClusterKeyForking + opts.Consumer.Cluster = constant.ClusterKeyForking } } -func WithClusterZoneAware() ClientOption { +func WithClientClusterZoneAware() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Cluster = constant.ClusterKeyZoneAware + opts.Consumer.Cluster = constant.ClusterKeyZoneAware } } -func WithClusterAdaptiveService() ClientOption { +func WithClientClusterAdaptiveService() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Cluster = constant.ClusterKeyAdaptiveService + opts.Consumer.Cluster = constant.ClusterKeyAdaptiveService } } // ========== LoadBalance Strategy ========== -func WithLoadBalanceConsistentHashing() ClientOption { +func WithClientLoadBalanceConsistentHashing() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Loadbalance = constant.LoadBalanceKeyConsistentHashing + opts.Consumer.Loadbalance = constant.LoadBalanceKeyConsistentHashing } } -func WithLoadBalanceLeastActive() ClientOption { +func WithClientLoadBalanceLeastActive() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Loadbalance = constant.LoadBalanceKeyLeastActive + opts.Consumer.Loadbalance = constant.LoadBalanceKeyLeastActive } } -func WithLoadBalanceRandom() ClientOption { +func WithClientLoadBalanceRandom() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Loadbalance = constant.LoadBalanceKeyRandom + opts.Consumer.Loadbalance = constant.LoadBalanceKeyRandom } } -func WithLoadBalanceRoundRobin() ClientOption { +func WithClientLoadBalanceRoundRobin() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Loadbalance = constant.LoadBalanceKeyRoundRobin + opts.Consumer.Loadbalance = constant.LoadBalanceKeyRoundRobin } } -func WithLoadBalanceP2C() ClientOption { +func WithClientLoadBalanceP2C() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Loadbalance = constant.LoadBalanceKeyP2C + opts.Consumer.Loadbalance = constant.LoadBalanceKeyP2C } } -func WithLoadBalanceXDSRingHash() ClientOption { +func WithClientLoadBalanceXDSRingHash() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Loadbalance = constant.LoadBalanceKeyLeastActive + opts.Consumer.Loadbalance = constant.LoadBalanceKeyLeastActive } } -func WithRetries(retries int) ClientOption { +func WithClientRetries(retries int) ClientOption { return func(opts *ClientOptions) { - opts.Reference.Retries = strconv.Itoa(retries) + opts.Consumer.Retries = strconv.Itoa(retries) } } -func WithGroup(group string) ClientOption { +func WithClientGroup(group string) ClientOption { return func(opts *ClientOptions) { - opts.Reference.Group = group + opts.Consumer.Group = group } } -func WithVersion(version string) ClientOption { +func WithClientVersion(version string) ClientOption { return func(opts *ClientOptions) { - opts.Reference.Version = version + opts.Consumer.Version = version } } -func WithJSON() ClientOption { +func WithClientJSON() ClientOption { return func(opts *ClientOptions) { - opts.Reference.Serialization = constant.JSONSerialization + opts.Consumer.Serialization = constant.JSONSerialization } } -func WithProvidedBy(providedBy string) ClientOption { +func WithClientProvidedBy(providedBy string) ClientOption { return func(opts *ClientOptions) { - opts.Reference.ProvidedBy = providedBy + opts.Consumer.ProvidedBy = providedBy } } // todo(DMwangnima): implement this functionality //func WithAsync() ClientOption { // return func(opts *ClientOptions) { -// opts.Reference.Async = true +// opts.Consumer.Async = true // } //} -func WithParams(params map[string]string) ClientOption { +func WithClientParams(params map[string]string) ClientOption { return func(opts *ClientOptions) { - opts.Reference.Params = params + opts.Consumer.Params = params } } // todo(DMwangnima): implement this functionality -//func WithGeneric(generic bool) ClientOption { +//func WithClientGeneric(generic bool) ClientOption { // return func(opts *ClientOptions) { // if generic { -// opts.Reference.Generic = "true" +// opts.Consumer.Generic = "true" // } else { -// opts.Reference.Generic = "false" +// opts.Consumer.Generic = "false" // } // } //} -func WithSticky(sticky bool) ClientOption { +func WithClientSticky(sticky bool) ClientOption { return func(opts *ClientOptions) { - opts.Reference.Sticky = sticky + opts.Consumer.Sticky = sticky } } -func WithRequestTimeout(timeout time.Duration) ClientOption { +// ========== Protocol to consume ========== + +func WithClientProtocolDubbo() ClientOption { return func(opts *ClientOptions) { - opts.Reference.RequestTimeout = timeout.String() + opts.Consumer.Protocol = constant.Dubbo } } -func WithForce(force bool) ClientOption { +func WithClientProtocolTriple() ClientOption { return func(opts *ClientOptions) { - opts.Reference.ForceTag = force + opts.Consumer.Protocol = "tri" } } -func WithMeshProviderPort(port int) ClientOption { +func WithClientProtocolJsonRPC() ClientOption { return func(opts *ClientOptions) { - opts.Reference.MeshProviderPort = port + opts.Consumer.Protocol = "jsonrpc" } } -// ---------- For framework ---------- -// These functions should not be invoked by users +func WithClientProtocol(protocol string) ClientOption { Review Comment: ditto. ########## client/client.go: ########## @@ -45,7 +47,7 @@ type ClientInfo struct { Meta map[string]interface{} } -func (cli *Client) call(ctx context.Context, paramsRawVals []interface{}, interfaceName, methodName, callType string, opts ...CallOption) (protocol.Result, error) { +func (cli *Client) call(ctx context.Context, paramsRawVals []interface{}, interfaceName, methodName, group, version, callType string, opts ...CallOption) (protocol.Result, error) { Review Comment: We need to consider that whether ```group``` and ```version``` should be required fields. Since this function is relevant to non-idl API, we need to keep it simple. For instance, if users do not need to configure ```group``` and ```version```, ``` cli.CallUnary(ctx, req, resp, interfaceName, methodName, "", "") ``` Empty strings are very redundant. I prefer to use ```CallOption``` to carry ```group``` and ```version```. ########## client/client.go: ########## @@ -57,52 +59,65 @@ func (cli *Client) call(ctx context.Context, paramsRawVals []interface{}, interf if err != nil { return nil, err } + + refOption := cli.refOpts[common.ServiceKey(interfaceName, group, version)] + if refOption == nil { + return nil, fmt.Errorf("no service found for %s/%s:%s, please check if the service has been registered", group, interfaceName, version) + } // todo: move timeout into context or invocation - return cli.invoker.Invoke(ctx, inv), nil + return refOption.invoker.Invoke(ctx, inv), nil } -func (cli *Client) CallUnary(ctx context.Context, req, resp interface{}, interfaceName, methodName string, opts ...CallOption) error { - res, err := cli.call(ctx, []interface{}{req, resp}, interfaceName, methodName, constant.CallUnary, opts...) +func (cli *Client) CallUnary(ctx context.Context, req, resp interface{}, interfaceName, methodName string, group string, version string, opts ...CallOption) error { + res, err := cli.call(ctx, []interface{}{req, resp}, interfaceName, methodName, group, version, constant.CallUnary, opts...) if err != nil { return err } return res.Error() } -func (cli *Client) CallClientStream(ctx context.Context, interfaceName, methodName string, opts ...CallOption) (interface{}, error) { - res, err := cli.call(ctx, nil, interfaceName, methodName, constant.CallClientStream, opts...) +func (cli *Client) CallClientStream(ctx context.Context, interfaceName, methodName, group, version string, opts ...CallOption) (interface{}, error) { + res, err := cli.call(ctx, nil, interfaceName, methodName, group, version, constant.CallClientStream, opts...) if err != nil { return nil, err } return res.Result(), res.Error() } -func (cli *Client) CallServerStream(ctx context.Context, req interface{}, interfaceName, methodName string, opts ...CallOption) (interface{}, error) { - res, err := cli.call(ctx, []interface{}{req}, interfaceName, methodName, constant.CallServerStream, opts...) +func (cli *Client) CallServerStream(ctx context.Context, req interface{}, interfaceName, methodName, group, version string, opts ...CallOption) (interface{}, error) { + res, err := cli.call(ctx, []interface{}{req}, interfaceName, methodName, group, version, constant.CallServerStream, opts...) if err != nil { return nil, err } return res.Result(), res.Error() } -func (cli *Client) CallBidiStream(ctx context.Context, interfaceName, methodName string, opts ...CallOption) (interface{}, error) { - res, err := cli.call(ctx, nil, interfaceName, methodName, constant.CallBidiStream, opts...) +func (cli *Client) CallBidiStream(ctx context.Context, interfaceName, methodName, group, version string, opts ...CallOption) (interface{}, error) { + res, err := cli.call(ctx, nil, interfaceName, methodName, group, version, constant.CallBidiStream, opts...) if err != nil { return nil, err } return res.Result(), res.Error() } -func (cli *Client) Init(info *ClientInfo) error { +func (cli *Client) Init(interfaceName string, info *ClientInfo, opts ...ReferenceOption) (string, string, error) { Review Comment: ```ClientInfo``` contains ```InterfaceName```. And we also need to consider about non-idl API style since this function is also important. ########## client/options_test.go: ########## @@ -17,49 +17,37 @@ package client -import ( - "testing" -) - -import ( - "github.com/stretchr/testify/assert" -) - -import ( - "dubbo.apache.org/dubbo-go/v3/common" -) - -func TestWithURL(t *testing.T) { - tests := []struct { - opts []ClientOption - justify func(t *testing.T, opts *ClientOptions) - }{ - { - opts: []ClientOption{ - WithURL("127.0.0.1:20000"), - }, - justify: func(t *testing.T, opts *ClientOptions) { - urls := opts.urls - assert.Equal(t, 1, len(urls)) - assert.Equal(t, "tri", urls[0].Protocol) - }, - }, - { - opts: []ClientOption{ - WithURL("tri://127.0.0.1:20000"), - }, - justify: func(t *testing.T, opts *ClientOptions) { - urls := opts.urls - assert.Equal(t, 1, len(urls)) - assert.Equal(t, "tri", urls[0].Protocol) - }, - }, - } - - for _, test := range tests { - newOpts := defaultClientOptions() - assert.Nil(t, newOpts.init(test.opts...)) - assert.Nil(t, newOpts.processURL(&common.URL{})) - test.justify(t, newOpts) - } -} +//func TestWithURL(t *testing.T) { Review Comment: After merging this PR, we can modify this test file. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
