This is an automated email from the ASF dual-hosted git repository.
liujun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git
The following commit(s) were added to refs/heads/main by this push:
new 8efb9ea90 feat: deep copy the configuration when instanceOptions flow
to ServerOptions/ClientOptions (#2596)
8efb9ea90 is described below
commit 8efb9ea902733e0fd7d947df13e0091c07b820ea
Author: setcy <[email protected]>
AuthorDate: Thu Feb 29 10:26:10 2024 +0800
feat: deep copy the configuration when instanceOptions flow to
ServerOptions/ClientOptions (#2596)
fixes #2592
---
dubbo.go | 24 ++--
dubbo_test.go | 98 +++++++++++++
global/application_config.go | 19 +++
global/config_center_config.go | 27 ++++
global/config_test.go | 300 +++++++++++++++++++++++++++++++++++++++
global/consumer_config.go | 30 ++++
global/custom_config.go | 20 ++-
global/logger_config.go | 36 +++++
global/metadata_report_config.go | 24 ++++
global/method_config.go | 23 +++
global/metric_config.go | 109 ++++++++++++++
global/otel_config.go | 33 +++++
global/profiles_config.go | 11 ++
global/protocol_config.go | 16 +++
global/provider_config.go | 38 +++++
global/reference_config.go | 54 +++++++
global/registry_config.go | 31 ++++
global/service_config.go | 66 +++++++++
global/shutdown_config.go | 29 ++++
global/tls_config.go | 14 ++
options.go | 106 ++++++++++++++
21 files changed, 1095 insertions(+), 13 deletions(-)
diff --git a/dubbo.go b/dubbo.go
index b779b78f7..ea9739b81 100644
--- a/dubbo.go
+++ b/dubbo.go
@@ -70,12 +70,12 @@ func (ins *Instance) NewClient(opts ...client.ClientOption)
(*client.Client, err
}
var cliOpts []client.ClientOption
- conCfg := ins.insOpts.Consumer
- appCfg := ins.insOpts.Application
- regsCfg := ins.insOpts.Registries
- sdCfg := ins.insOpts.Shutdown
- metricsCfg := ins.insOpts.Metrics
- otelCfg := ins.insOpts.Otel
+ conCfg := ins.insOpts.CloneConsumer()
+ appCfg := ins.insOpts.CloneApplication()
+ regsCfg := ins.insOpts.CloneRegistries()
+ sdCfg := ins.insOpts.CloneShutdown()
+ metricsCfg := ins.insOpts.CloneMetrics()
+ otelCfg := ins.insOpts.CloneOtel()
if conCfg != nil {
if conCfg.Check {
@@ -125,12 +125,12 @@ func (ins *Instance) NewServer(opts
...server.ServerOption) (*server.Server, err
}
var srvOpts []server.ServerOption
- appCfg := ins.insOpts.Application
- regsCfg := ins.insOpts.Registries
- prosCfg := ins.insOpts.Protocols
- sdCfg := ins.insOpts.Shutdown
- metricsCfg := ins.insOpts.Metrics
- otelCfg := ins.insOpts.Otel
+ appCfg := ins.insOpts.CloneApplication()
+ regsCfg := ins.insOpts.CloneRegistries()
+ prosCfg := ins.insOpts.CloneProtocols()
+ sdCfg := ins.insOpts.CloneShutdown()
+ metricsCfg := ins.insOpts.CloneMetrics()
+ otelCfg := ins.insOpts.CloneOtel()
if appCfg != nil {
srvOpts = append(srvOpts,
diff --git a/dubbo_test.go b/dubbo_test.go
new file mode 100644
index 000000000..e23c97394
--- /dev/null
+++ b/dubbo_test.go
@@ -0,0 +1,98 @@
+/*
+ * 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 dubbo
+
+import (
+ "testing"
+)
+
+import (
+ "github.com/stretchr/testify/assert"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/client"
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+ "dubbo.apache.org/dubbo-go/v3/registry"
+ "dubbo.apache.org/dubbo-go/v3/server"
+)
+
+// TestIndependentConfig tests the configurations of the `instance`, `client`,
and `server` are independent.
+func TestIndependentConfig(t *testing.T) {
+ // instance configuration
+ ins, err := NewInstance(
+ WithName("dubbo_test"),
+ WithRegistry(
+ registry.WithZookeeper(),
+ registry.WithAddress("127.0.0.1:2181"),
+ ),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // client configuration, ensure that the `instance` configuration can
be passed to the `client`.
+ _, err = ins.NewClient(
+ func(options *client.ClientOptions) {
+ assert.Equal(t, "dubbo_test", options.Application.Name)
+ options.Application.Name = "dubbo_test_client"
+ assert.Equal(t, "dubbo_test_client",
options.Application.Name)
+
+ assert.Equal(t, "127.0.0.1:2181",
options.Registries[constant.ZookeeperKey].Address)
+ options.Registries[constant.ZookeeperKey].Address =
"127.0.0.1:2182"
+ assert.Equal(t, "127.0.0.1:2182",
options.Registries[constant.ZookeeperKey].Address)
+ },
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // server configuration, ensure that the `instance` configuration can
be passed to the `server`, and the
+ // `instance` configuration is not affected by the `client`
configuration.
+ _, err = ins.NewServer(
+ func(options *server.ServerOptions) {
+ assert.Equal(t, "dubbo_test", options.Application.Name)
+ options.Application.Name = "dubbo_test_server"
+ assert.Equal(t, "dubbo_test_server",
options.Application.Name)
+
+ assert.Equal(t, "127.0.0.1:2181",
options.Registries[constant.ZookeeperKey].Address)
+ options.Registries[constant.ZookeeperKey].Address =
"127.0.0.1:2183"
+ assert.Equal(t, "127.0.0.1:2183",
options.Registries[constant.ZookeeperKey].Address)
+ },
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // check client configuration again, ensure that the `instance` and
`client` configuration is not affected
+ // by the `server` configuration.
+ _, err = ins.NewClient(
+ func(options *client.ClientOptions) {
+ assert.Equal(t, "dubbo_test", options.Application.Name)
+ options.Application.Name = "dubbo_test_client"
+ assert.Equal(t, "dubbo_test_client",
options.Application.Name)
+
+ assert.Equal(t, "127.0.0.1:2181",
options.Registries[constant.ZookeeperKey].Address)
+ options.Registries[constant.ZookeeperKey].Address =
"127.0.0.1:2184"
+ assert.Equal(t, "127.0.0.1:2184",
options.Registries[constant.ZookeeperKey].Address)
+ },
+ )
+ if err != nil {
+ panic(err)
+ }
+}
diff --git a/global/application_config.go b/global/application_config.go
index 426378caf..0eab19d8e 100644
--- a/global/application_config.go
+++ b/global/application_config.go
@@ -35,3 +35,22 @@ func DefaultApplicationConfig() *ApplicationConfig {
// return a new config without setting any field means there is not any
default value for initialization
return &ApplicationConfig{}
}
+
+// Clone a new ApplicationConfig
+func (c *ApplicationConfig) Clone() *ApplicationConfig {
+ if c == nil {
+ return nil
+ }
+
+ return &ApplicationConfig{
+ Organization: c.Organization,
+ Name: c.Name,
+ Module: c.Module,
+ Group: c.Group,
+ Version: c.Version,
+ Owner: c.Owner,
+ Environment: c.Environment,
+ MetadataType: c.MetadataType,
+ Tag: c.Tag,
+ }
+}
diff --git a/global/config_center_config.go b/global/config_center_config.go
index 75c58fb99..debb0676d 100644
--- a/global/config_center_config.go
+++ b/global/config_center_config.go
@@ -46,3 +46,30 @@ func DefaultCenterConfig() *CenterConfig {
Params: make(map[string]string),
}
}
+
+// Clone a new CenterConfig
+func (c *CenterConfig) Clone() *CenterConfig {
+ if c == nil {
+ return nil
+ }
+
+ newParams := make(map[string]string, len(c.Params))
+ for k, v := range c.Params {
+ newParams[k] = v
+ }
+
+ return &CenterConfig{
+ Protocol: c.Protocol,
+ Address: c.Address,
+ DataId: c.DataId,
+ Cluster: c.Cluster,
+ Group: c.Group,
+ Username: c.Username,
+ Password: c.Password,
+ Namespace: c.Namespace,
+ AppID: c.AppID,
+ Timeout: c.Timeout,
+ Params: newParams,
+ FileExtension: c.FileExtension,
+ }
+}
diff --git a/global/config_test.go b/global/config_test.go
new file mode 100644
index 000000000..6b466abb4
--- /dev/null
+++ b/global/config_test.go
@@ -0,0 +1,300 @@
+/*
+ * 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 global
+
+import (
+ "reflect"
+ "testing"
+)
+
+import (
+ "github.com/stretchr/testify/assert"
+)
+
+// TestCloneConfig tests the Clone method of the *_config.go files
+func TestCloneConfig(t *testing.T) {
+ t.Run("ApplicationConfig", func(t *testing.T) {
+ c := DefaultApplicationConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("ConfigCenterConfig", func(t *testing.T) {
+ c := DefaultCenterConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("ConsumerConfig", func(t *testing.T) {
+ c := DefaultConsumerConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("CustomConfig", func(t *testing.T) {
+ c := DefaultCustomConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("LoggerConfig", func(t *testing.T) {
+ c := DefaultLoggerConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("MetadataReportConfig", func(t *testing.T) {
+ c := DefaultMetadataReportConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("MethodConfig", func(t *testing.T) {
+ c := &MethodConfig{}
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("MetricConfig", func(t *testing.T) {
+ c := DefaultMetricsConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+
+ c2 := &AggregateConfig{}
+ InitCheckCompleteInequality(t, c2)
+ clone2 := c2.Clone()
+ CheckCompleteInequality(t, c2, clone2)
+
+ c3 := &PrometheusConfig{}
+ InitCheckCompleteInequality(t, c3)
+ clone3 := c3.Clone()
+ CheckCompleteInequality(t, c3, clone3)
+
+ c4 := &Exporter{}
+ InitCheckCompleteInequality(t, c4)
+ clone4 := c4.Clone()
+ CheckCompleteInequality(t, c4, clone4)
+
+ c5 := &PushgatewayConfig{}
+ InitCheckCompleteInequality(t, c5)
+ clone5 := c5.Clone()
+ CheckCompleteInequality(t, c5, clone5)
+ })
+
+ t.Run("OtelConfig", func(t *testing.T) {
+ c := DefaultOtelConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+
+ c2 := &OtelTraceConfig{}
+ InitCheckCompleteInequality(t, c2)
+ clone2 := c2.Clone()
+ CheckCompleteInequality(t, c2, clone2)
+ })
+
+ t.Run("ProfilesConfig", func(t *testing.T) {
+ c := DefaultProfilesConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("ProtocolConfig", func(t *testing.T) {
+ c := DefaultProtocolConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("ProviderConfig", func(t *testing.T) {
+ c := DefaultProviderConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("ReferenceConfig", func(t *testing.T) {
+ c := DefaultReferenceConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("RegistryConfig", func(t *testing.T) {
+ c := DefaultRegistryConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("ServiceConfig", func(t *testing.T) {
+ c := DefaultServiceConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("ShutdownConfig", func(t *testing.T) {
+ c := DefaultShutdownConfig()
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+
+ t.Run("TLSConfig", func(t *testing.T) {
+ c := &TLSConfig{}
+ InitCheckCompleteInequality(t, c)
+ clone := c.Clone()
+ CheckCompleteInequality(t, c, clone)
+ })
+}
+
+func InitCheckCompleteInequality(t *testing.T, origin interface{}) {
+ if origin == nil {
+ t.Errorf("Invalid parameters")
+ return
+ }
+
+ originValue := reflect.ValueOf(origin).Elem()
+
+ if originValue.Kind() != reflect.Struct {
+ t.Errorf("Parameters should be struct types.")
+ return
+ }
+
+ for i := 0; i < originValue.NumField(); i++ {
+ originField := originValue.Field(i)
+
+ if !originField.CanSet() {
+ // Field '%s' is unexported, skipping checking
+ continue
+ }
+
+ switch originField.Kind() {
+ case reflect.String:
+ originField.SetString("origin")
+
+ case reflect.Bool:
+ originField.SetBool(true)
+
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
reflect.Int64:
+ originField.SetInt(1)
+
+ case reflect.Uint, reflect.Uint8, reflect.Uint16,
reflect.Uint32, reflect.Uint64:
+ originField.SetUint(1)
+
+ case reflect.Float32, reflect.Float64:
+ originField.SetFloat(1.5)
+
+ case reflect.Map:
+ originField.Set(reflect.MakeMap(originField.Type()))
+
+ case reflect.Slice, reflect.Ptr:
+
+ default:
+ // Field '%s' is of unsupported type '%s', skipping
checking
+ }
+ }
+}
+
+func CheckCompleteInequality(t *testing.T, origin interface{}, clone
interface{}) {
+ if origin == nil || clone == nil {
+ t.Errorf("Invalid parameters")
+ return
+ }
+
+ assert.NotSame(t, origin, clone)
+
+ originValue := reflect.ValueOf(origin).Elem()
+ cloneValue := reflect.ValueOf(clone).Elem()
+
+ if originValue.Kind() != reflect.Struct || cloneValue.Kind() !=
reflect.Struct {
+ t.Errorf("Both parameters should be struct types.")
+ return
+ }
+
+ if originValue.Type() != cloneValue.Type() {
+ t.Errorf("Parameters should be of the same type.")
+ return
+ }
+
+ for i := 0; i < originValue.NumField(); i++ {
+ originField := originValue.Field(i)
+ cloneField := cloneValue.Field(i)
+
+ if !originField.CanSet() {
+ t.Logf("Field '%s' is unexported, skipping checking",
originValue.Type().Field(i).Name)
+ continue
+ }
+
+ switch originField.Kind() {
+ case reflect.String:
+ assert.Equal(t, "origin", cloneField.String())
+ cloneField.SetString("clone")
+ assert.Equal(t, "clone", cloneField.String())
+ assert.Equal(t, "origin", originField.String())
+
+ case reflect.Bool:
+ assert.Equal(t, true, cloneField.Bool())
+ cloneField.SetBool(false)
+ assert.Equal(t, false, cloneField.Bool())
+ assert.Equal(t, true, originField.Bool())
+
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
reflect.Int64:
+ assert.EqualValues(t, 1, cloneField.Int())
+ cloneField.SetInt(2)
+ assert.EqualValues(t, 2, cloneField.Int())
+ assert.EqualValues(t, 1, originField.Int())
+
+ case reflect.Uint, reflect.Uint8, reflect.Uint16,
reflect.Uint32, reflect.Uint64:
+ assert.EqualValues(t, 1, cloneField.Uint())
+ cloneField.SetUint(2)
+ assert.EqualValues(t, 2, cloneField.Uint())
+ assert.EqualValues(t, 1, originField.Uint())
+
+ case reflect.Float32, reflect.Float64:
+ assert.EqualValues(t, 1.5, cloneField.Float())
+ cloneField.SetFloat(2.5)
+ assert.EqualValues(t, 2.5, cloneField.Float())
+ assert.EqualValues(t, 1.5, originField.Float())
+
+ case reflect.Map, reflect.Ptr:
+ if originField.IsNil() {
+ assert.Zero(t, cloneField.Pointer())
+ } else {
+ assert.NotZero(t, cloneField.Pointer())
+ assert.NotEqual(t, originField.Pointer(),
cloneField.Pointer())
+ }
+
+ case reflect.Slice:
+ assert.NotEqual(t, originField.Pointer(),
cloneField.Pointer())
+
+ default:
+ t.Logf("Field '%s' is of unsupported type '%s',
skipping checking", originValue.Type().Field(i).Name, originField.Kind())
+ }
+ }
+}
diff --git a/global/consumer_config.go b/global/consumer_config.go
index ee7c21e02..7c3afaac3 100644
--- a/global/consumer_config.go
+++ b/global/consumer_config.go
@@ -40,3 +40,33 @@ func DefaultConsumerConfig() *ConsumerConfig {
References: make(map[string]*ReferenceConfig),
}
}
+
+// Clone a new ConsumerConfig
+func (c *ConsumerConfig) Clone() *ConsumerConfig {
+ if c == nil {
+ return nil
+ }
+
+ newRegistryIDs := make([]string, len(c.RegistryIDs))
+ copy(newRegistryIDs, c.RegistryIDs)
+
+ newReferences := make(map[string]*ReferenceConfig, len(c.References))
+ for k, v := range c.References {
+ newReferences[k] = v.Clone()
+ }
+
+ return &ConsumerConfig{
+ Filter: c.Filter,
+ RegistryIDs: newRegistryIDs,
+ Protocol: c.Protocol,
+ RequestTimeout: c.RequestTimeout,
+ ProxyFactory: c.ProxyFactory,
+ Check: c.Check,
+ AdaptiveService: c.AdaptiveService,
+ References: newReferences,
+ TracingKey: c.TracingKey,
+ FilterConf: c.FilterConf,
+ MaxWaitTimeForServiceDiscovery:
c.MaxWaitTimeForServiceDiscovery,
+ MeshEnabled: c.MeshEnabled,
+ }
+}
diff --git a/global/custom_config.go b/global/custom_config.go
index 0e418a779..107f0207c 100644
--- a/global/custom_config.go
+++ b/global/custom_config.go
@@ -28,5 +28,23 @@ type CustomConfig struct {
}
func DefaultCustomConfig() *CustomConfig {
- return &CustomConfig{}
+ return &CustomConfig{
+ ConfigMap: make(map[string]interface{}),
+ }
+}
+
+// Clone a new CustomConfig
+func (c *CustomConfig) Clone() *CustomConfig {
+ if c == nil {
+ return nil
+ }
+
+ newConfigMap := make(map[string]interface{}, len(c.ConfigMap))
+ for k, v := range c.ConfigMap {
+ newConfigMap[k] = v
+ }
+
+ return &CustomConfig{
+ ConfigMap: newConfigMap,
+ }
}
diff --git a/global/logger_config.go b/global/logger_config.go
index 0f94a3dcd..32315d6fd 100644
--- a/global/logger_config.go
+++ b/global/logger_config.go
@@ -63,3 +63,39 @@ func DefaultLoggerConfig() *LoggerConfig {
return cfg
}
+
+// Clone a new LoggerConfig
+func (c *LoggerConfig) Clone() *LoggerConfig {
+ if c == nil {
+ return nil
+ }
+
+ return &LoggerConfig{
+ Driver: c.Driver,
+ Level: c.Level,
+ Format: c.Format,
+ Appender: c.Appender,
+ File: c.File.Clone(),
+ }
+}
+
+// Clone a new File
+func (f *File) Clone() *File {
+ if f == nil {
+ return nil
+ }
+
+ var newCompress *bool
+ if f.Compress != nil {
+ newCompress = new(bool)
+ *newCompress = *f.Compress
+ }
+
+ return &File{
+ Name: f.Name,
+ MaxSize: f.MaxSize,
+ MaxBackups: f.MaxBackups,
+ MaxAge: f.MaxAge,
+ Compress: f.Compress,
+ }
+}
diff --git a/global/metadata_report_config.go b/global/metadata_report_config.go
index bac446e84..bf54fc16f 100644
--- a/global/metadata_report_config.go
+++ b/global/metadata_report_config.go
@@ -35,3 +35,27 @@ func DefaultMetadataReportConfig() *MetadataReportConfig {
// return a new config without setting any field means there is not any
default value for initialization
return &MetadataReportConfig{Params: map[string]string{}}
}
+
+// Clone a new MetadataReportConfig
+func (c *MetadataReportConfig) Clone() *MetadataReportConfig {
+ if c == nil {
+ return nil
+ }
+
+ newParams := make(map[string]string, len(c.Params))
+ for k, v := range c.Params {
+ newParams[k] = v
+ }
+
+ return &MetadataReportConfig{
+ Protocol: c.Protocol,
+ Address: c.Address,
+ Username: c.Username,
+ Password: c.Password,
+ Timeout: c.Timeout,
+ Group: c.Group,
+ Namespace: c.Namespace,
+ Params: newParams,
+ metadataType: c.metadataType,
+ }
+}
diff --git a/global/method_config.go b/global/method_config.go
index 08630745a..e22ae0fbb 100644
--- a/global/method_config.go
+++ b/global/method_config.go
@@ -33,3 +33,26 @@ type MethodConfig struct {
Sticky bool `yaml:"sticky"
json:"sticky,omitempty" property:"sticky"`
RequestTimeout string `yaml:"timeout"
json:"timeout,omitempty" property:"timeout"`
}
+
+// Clone a new MethodConfig
+func (c *MethodConfig) Clone() *MethodConfig {
+ if c == nil {
+ return nil
+ }
+
+ return &MethodConfig{
+ InterfaceId: c.InterfaceId,
+ InterfaceName: c.InterfaceName,
+ Name: c.Name,
+ Retries: c.Retries,
+ LoadBalance: c.LoadBalance,
+ Weight: c.Weight,
+ TpsLimitInterval: c.TpsLimitInterval,
+ TpsLimitRate: c.TpsLimitRate,
+ TpsLimitStrategy: c.TpsLimitStrategy,
+ ExecuteLimit: c.ExecuteLimit,
+ ExecuteLimitRejectedHandler: c.ExecuteLimitRejectedHandler,
+ Sticky: c.Sticky,
+ RequestTimeout: c.RequestTimeout,
+ }
+}
diff --git a/global/metric_config.go b/global/metric_config.go
index 44f4c6b39..88f296463 100644
--- a/global/metric_config.go
+++ b/global/metric_config.go
@@ -60,10 +60,119 @@ func DefaultMetricsConfig() *MetricsConfig {
return &MetricsConfig{Prometheus: defaultPrometheusConfig(),
Aggregation: defaultAggregateConfig()}
}
+// Clone a new MetricsConfig
+func (c *MetricsConfig) Clone() *MetricsConfig {
+ if c == nil {
+ return nil
+ }
+
+ var newEnable *bool
+ if c.Enable != nil {
+ newEnable = new(bool)
+ *newEnable = *c.Enable
+ }
+
+ var newEnableMetadata *bool
+ if c.EnableMetadata != nil {
+ newEnableMetadata = new(bool)
+ *newEnableMetadata = *c.EnableMetadata
+ }
+
+ var newEnableRegistry *bool
+ if c.EnableRegistry != nil {
+ newEnableRegistry = new(bool)
+ *newEnableRegistry = *c.EnableRegistry
+ }
+
+ var newEnableConfigCenter *bool
+ if c.EnableConfigCenter != nil {
+ newEnableConfigCenter = new(bool)
+ *newEnableConfigCenter = *c.EnableConfigCenter
+ }
+
+ return &MetricsConfig{
+ Enable: newEnable,
+ Port: c.Port,
+ Path: c.Path,
+ Protocol: c.Protocol,
+ Prometheus: c.Prometheus.Clone(),
+ Aggregation: c.Aggregation.Clone(),
+ EnableMetadata: newEnableMetadata,
+ EnableRegistry: newEnableRegistry,
+ EnableConfigCenter: newEnableConfigCenter,
+ }
+}
+
func defaultPrometheusConfig() *PrometheusConfig {
return &PrometheusConfig{Exporter: &Exporter{}, Pushgateway:
&PushgatewayConfig{}}
}
+func (c *PrometheusConfig) Clone() *PrometheusConfig {
+ if c == nil {
+ return nil
+ }
+
+ return &PrometheusConfig{
+ Exporter: c.Exporter.Clone(),
+ Pushgateway: c.Pushgateway.Clone(),
+ }
+}
+
+func (c *Exporter) Clone() *Exporter {
+ if c == nil {
+ return nil
+ }
+
+ var newEnabled *bool
+ if c.Enabled != nil {
+ newEnabled = new(bool)
+ *newEnabled = *c.Enabled
+ }
+
+ return &Exporter{
+ Enabled: newEnabled,
+ }
+}
+
+func (c *PushgatewayConfig) Clone() *PushgatewayConfig {
+ if c == nil {
+ return nil
+ }
+
+ var newEnabled *bool
+ if c.Enabled != nil {
+ newEnabled = new(bool)
+ *newEnabled = *c.Enabled
+ }
+
+ return &PushgatewayConfig{
+ Enabled: newEnabled,
+ BaseUrl: c.BaseUrl,
+ Job: c.Job,
+ Username: c.Username,
+ Password: c.Password,
+ PushInterval: c.PushInterval,
+ }
+}
+
func defaultAggregateConfig() *AggregateConfig {
return &AggregateConfig{}
}
+
+func (c *AggregateConfig) Clone() *AggregateConfig {
+ if c == nil {
+ return nil
+ }
+
+ var newEnabled *bool
+ if c.Enabled != nil {
+ newEnabled = new(bool)
+ *newEnabled = *c.Enabled
+ }
+
+ return &AggregateConfig{
+ Enabled: newEnabled,
+ BucketNum: c.BucketNum,
+ TimeWindowSeconds: c.TimeWindowSeconds,
+ }
+}
diff --git a/global/otel_config.go b/global/otel_config.go
index f41f8e773..fd4bbf243 100644
--- a/global/otel_config.go
+++ b/global/otel_config.go
@@ -36,3 +36,36 @@ func DefaultOtelConfig() *OtelConfig {
TracingConfig: &OtelTraceConfig{},
}
}
+
+// Clone a new OtelConfig
+func (c *OtelConfig) Clone() *OtelConfig {
+ if c == nil {
+ return nil
+ }
+
+ return &OtelConfig{
+ TracingConfig: c.TracingConfig.Clone(),
+ }
+}
+
+// Clone a new OtelTraceConfig
+func (c *OtelTraceConfig) Clone() *OtelTraceConfig {
+ if c == nil {
+ return nil
+ }
+
+ var newEnable *bool
+ if c.Enable != nil {
+ newEnable = new(bool)
+ *newEnable = *c.Enable
+ }
+
+ return &OtelTraceConfig{
+ Enable: newEnable,
+ Exporter: c.Exporter,
+ Endpoint: c.Endpoint,
+ Propagator: c.Propagator,
+ SampleMode: c.SampleMode,
+ SampleRatio: c.SampleRatio,
+ }
+}
diff --git a/global/profiles_config.go b/global/profiles_config.go
index d829dd836..77355788c 100644
--- a/global/profiles_config.go
+++ b/global/profiles_config.go
@@ -26,6 +26,17 @@ func DefaultProfilesConfig() *ProfilesConfig {
return &ProfilesConfig{}
}
+// Clone a new ProfilesConfig
+func (c *ProfilesConfig) Clone() *ProfilesConfig {
+ if c == nil {
+ return nil
+ }
+
+ return &ProfilesConfig{
+ Active: c.Active,
+ }
+}
+
type ProfilesOption func(*ProfilesConfig)
func WithProfiles_Active(active string) ProfilesOption {
diff --git a/global/protocol_config.go b/global/protocol_config.go
index ebfa3dd5e..e2fff4cbd 100644
--- a/global/protocol_config.go
+++ b/global/protocol_config.go
@@ -34,3 +34,19 @@ type ProtocolConfig struct {
func DefaultProtocolConfig() *ProtocolConfig {
return &ProtocolConfig{}
}
+
+// Clone a new ProtocolConfig
+func (c *ProtocolConfig) Clone() *ProtocolConfig {
+ if c == nil {
+ return nil
+ }
+
+ return &ProtocolConfig{
+ Name: c.Name,
+ Ip: c.Ip,
+ Port: c.Port,
+ Params: c.Params,
+ MaxServerSendMsgSize: c.MaxServerSendMsgSize,
+ MaxServerRecvMsgSize: c.MaxServerRecvMsgSize,
+ }
+}
diff --git a/global/provider_config.go b/global/provider_config.go
index 3d7e30dd1..d5fd12985 100644
--- a/global/provider_config.go
+++ b/global/provider_config.go
@@ -47,3 +47,41 @@ func DefaultProviderConfig() *ProviderConfig {
Services: make(map[string]*ServiceConfig),
}
}
+
+// Clone a new ProviderConfig
+func (c *ProviderConfig) Clone() *ProviderConfig {
+ if c == nil {
+ return nil
+ }
+
+ newRegistryIDs := make([]string, len(c.RegistryIDs))
+ copy(newRegistryIDs, c.RegistryIDs)
+
+ newProtocolIDs := make([]string, len(c.ProtocolIDs))
+ copy(newProtocolIDs, c.ProtocolIDs)
+
+ newServices := make(map[string]*ServiceConfig, len(c.Services))
+ for k, v := range c.Services {
+ newServices[k] = v.Clone()
+ }
+
+ newConfigType := make(map[string]string, len(c.ConfigType))
+ for k, v := range c.ConfigType {
+ newConfigType[k] = v
+ }
+
+ return &ProviderConfig{
+ ServiceConfig: *c.ServiceConfig.Clone(),
+ Filter: c.Filter,
+ Register: c.Register,
+ RegistryIDs: newRegistryIDs,
+ ProtocolIDs: newProtocolIDs,
+ TracingKey: c.TracingKey,
+ Services: newServices,
+ ProxyFactory: c.ProxyFactory,
+ FilterConf: c.FilterConf,
+ ConfigType: newConfigType,
+ AdaptiveService: c.AdaptiveService,
+ AdaptiveServiceVerbose: c.AdaptiveServiceVerbose,
+ }
+}
diff --git a/global/reference_config.go b/global/reference_config.go
index 5acb6427f..1c24b61dc 100644
--- a/global/reference_config.go
+++ b/global/reference_config.go
@@ -56,6 +56,60 @@ func DefaultReferenceConfig() *ReferenceConfig {
}
}
+// Clone a new ReferenceConfig
+func (c *ReferenceConfig) Clone() *ReferenceConfig {
+ if c == nil {
+ return nil
+ }
+
+ var newCheck *bool
+ if c.Check != nil {
+ check := *c.Check
+ newCheck = &check
+ }
+
+ newRegistryIDs := make([]string, len(c.RegistryIDs))
+ copy(newRegistryIDs, c.RegistryIDs)
+
+ var newMethods []*MethodConfig
+ if c.Methods != nil {
+ newMethods = make([]*MethodConfig, 0, len(c.Methods))
+ for _, method := range c.Methods {
+ newMethods = append(newMethods, method.Clone())
+ }
+ }
+
+ newParams := make(map[string]string, len(c.Params))
+ for k, v := range c.Params {
+ newParams[k] = v
+ }
+
+ return &ReferenceConfig{
+ InterfaceName: c.InterfaceName,
+ Check: newCheck,
+ URL: c.URL,
+ Filter: c.Filter,
+ Protocol: c.Protocol,
+ RegistryIDs: newRegistryIDs,
+ Cluster: c.Cluster,
+ Loadbalance: c.Loadbalance,
+ Retries: c.Retries,
+ Group: c.Group,
+ Version: c.Version,
+ Serialization: c.Serialization,
+ ProvidedBy: c.ProvidedBy,
+ Methods: newMethods,
+ Async: c.Async,
+ Params: newParams,
+ Generic: c.Generic,
+ Sticky: c.Sticky,
+ RequestTimeout: c.RequestTimeout,
+ ForceTag: c.ForceTag,
+ TracingKey: c.TracingKey,
+ MeshProviderPort: c.MeshProviderPort,
+ }
+}
+
type ReferenceOption func(*ReferenceConfig)
func WithReference_InterfaceName(name string) ReferenceOption {
diff --git a/global/registry_config.go b/global/registry_config.go
index 783dccd2b..0b6de89f1 100644
--- a/global/registry_config.go
+++ b/global/registry_config.go
@@ -44,3 +44,34 @@ type RegistryConfig struct {
func DefaultRegistryConfig() *RegistryConfig {
return &RegistryConfig{}
}
+
+// Clone a new RegistryConfig
+func (c *RegistryConfig) Clone() *RegistryConfig {
+ if c == nil {
+ return nil
+ }
+
+ newParams := make(map[string]string, len(c.Params))
+ for k, v := range c.Params {
+ newParams[k] = v
+ }
+
+ return &RegistryConfig{
+ Protocol: c.Protocol,
+ Timeout: c.Timeout,
+ Group: c.Group,
+ Namespace: c.Namespace,
+ TTL: c.TTL,
+ Address: c.Address,
+ Username: c.Username,
+ Password: c.Password,
+ Simplified: c.Simplified,
+ Preferred: c.Preferred,
+ Zone: c.Zone,
+ Weight: c.Weight,
+ Params: newParams,
+ RegistryType: c.RegistryType,
+ UseAsMetaReport: c.UseAsMetaReport,
+ UseAsConfigCenter: c.UseAsConfigCenter,
+ }
+}
diff --git a/global/service_config.go b/global/service_config.go
index 8fd3a3c3e..b1c097af0 100644
--- a/global/service_config.go
+++ b/global/service_config.go
@@ -62,3 +62,69 @@ func DefaultServiceConfig() *ServiceConfig {
RCRegistriesMap: make(map[string]*RegistryConfig),
}
}
+
+// Clone a new ServiceConfig
+func (c *ServiceConfig) Clone() *ServiceConfig {
+ if c == nil {
+ return nil
+ }
+
+ newProtocolIDs := make([]string, len(c.ProtocolIDs))
+ copy(newProtocolIDs, c.ProtocolIDs)
+
+ newRegistryIDs := make([]string, len(c.RegistryIDs))
+ copy(newRegistryIDs, c.RegistryIDs)
+
+ newMethods := make([]*MethodConfig, len(c.Methods))
+ for i, v := range c.Methods {
+ newMethods[i] = v.Clone()
+ }
+
+ newParams := make(map[string]string, len(c.Params))
+ for k, v := range c.Params {
+ newParams[k] = v
+ }
+
+ newRCProtocolsMap := make(map[string]*ProtocolConfig,
len(c.RCProtocolsMap))
+ for k, v := range c.RCProtocolsMap {
+ newRCProtocolsMap[k] = v.Clone()
+ }
+
+ newRCRegistriesMap := make(map[string]*RegistryConfig,
len(c.RCRegistriesMap))
+ for k, v := range c.RCRegistriesMap {
+ newRCRegistriesMap[k] = v.Clone()
+ }
+
+ return &ServiceConfig{
+ Filter: c.Filter,
+ ProtocolIDs: newProtocolIDs,
+ Interface: c.Interface,
+ RegistryIDs: newRegistryIDs,
+ Cluster: c.Cluster,
+ Loadbalance: c.Loadbalance,
+ Group: c.Group,
+ Version: c.Version,
+ Methods: newMethods,
+ Warmup: c.Warmup,
+ Retries: c.Retries,
+ Serialization: c.Serialization,
+ Params: newParams,
+ Token: c.Token,
+ AccessLog: c.AccessLog,
+ TpsLimiter: c.TpsLimiter,
+ TpsLimitInterval: c.TpsLimitInterval,
+ TpsLimitRate: c.TpsLimitRate,
+ TpsLimitStrategy: c.TpsLimitStrategy,
+ TpsLimitRejectedHandler: c.TpsLimitRejectedHandler,
+ ExecuteLimit: c.ExecuteLimit,
+ ExecuteLimitRejectedHandler: c.ExecuteLimitRejectedHandler,
+ Auth: c.Auth,
+ RCProtocolsMap: newRCProtocolsMap,
+ RCRegistriesMap: newRCRegistriesMap,
+ ProxyFactoryKey: c.ProxyFactoryKey,
+ NotRegister: c.NotRegister,
+ ParamSign: c.ParamSign,
+ Tag: c.Tag,
+ TracingKey: c.TracingKey,
+ }
+}
diff --git a/global/shutdown_config.go b/global/shutdown_config.go
index e55448912..18f3ecc4d 100644
--- a/global/shutdown_config.go
+++ b/global/shutdown_config.go
@@ -68,3 +68,32 @@ func DefaultShutdownConfig() *ShutdownConfig {
return cfg
}
+
+// Clone a new ShutdownConfig
+func (c *ShutdownConfig) Clone() *ShutdownConfig {
+ if c == nil {
+ return nil
+ }
+
+ var newInternalSignal *bool
+ if c.InternalSignal != nil {
+ newInternalSignal = new(bool)
+ *newInternalSignal = *c.InternalSignal
+ }
+
+ newShutdownConfig := &ShutdownConfig{
+ Timeout: c.Timeout,
+ StepTimeout: c.StepTimeout,
+ ConsumerUpdateWaitTime: c.ConsumerUpdateWaitTime,
+ RejectRequestHandler: c.RejectRequestHandler,
+ InternalSignal: newInternalSignal,
+ OfflineRequestWindowTimeout: c.OfflineRequestWindowTimeout,
+ }
+
+ newShutdownConfig.RejectRequest.Store(c.RejectRequest.Load())
+
newShutdownConfig.ConsumerActiveCount.Store(c.ConsumerActiveCount.Load())
+
newShutdownConfig.ProviderActiveCount.Store(c.ProviderActiveCount.Load())
+
newShutdownConfig.ProviderLastReceivedRequestTime.Store(c.ProviderLastReceivedRequestTime.Load())
+
+ return newShutdownConfig
+}
diff --git a/global/tls_config.go b/global/tls_config.go
index 3b30d199b..862d9b408 100644
--- a/global/tls_config.go
+++ b/global/tls_config.go
@@ -35,6 +35,20 @@ func DefaultTLSConfig() *TLSConfig {
return nil
}
+// Clone a new TLSConfig
+func (c *TLSConfig) Clone() *TLSConfig {
+ if c == nil {
+ return nil
+ }
+
+ return &TLSConfig{
+ CACertFile: c.CACertFile,
+ TLSCertFile: c.TLSCertFile,
+ TLSKeyFile: c.TLSKeyFile,
+ TLSServerName: c.TLSServerName,
+ }
+}
+
type TLSOption func(*TLSConfig)
func WithTLS_CACertFile(file string) TLSOption {
diff --git a/options.go b/options.go
index 0e6719473..fa3996c74 100644
--- a/options.go
+++ b/options.go
@@ -167,6 +167,112 @@ func (rc *InstanceOptions) Prefix() string {
return constant.Dubbo
}
+func (rc *InstanceOptions) CloneApplication() *global.ApplicationConfig {
+ if rc.Application == nil {
+ return nil
+ }
+ return rc.Application.Clone()
+}
+
+func (rc *InstanceOptions) CloneProtocols() map[string]*global.ProtocolConfig {
+ if rc.Protocols == nil {
+ return nil
+ }
+ protocols := make(map[string]*global.ProtocolConfig, len(rc.Protocols))
+ for k, v := range rc.Protocols {
+ protocols[k] = v.Clone()
+ }
+ return protocols
+}
+
+func (rc *InstanceOptions) CloneRegistries() map[string]*global.RegistryConfig
{
+ if rc.Registries == nil {
+ return nil
+ }
+ registries := make(map[string]*global.RegistryConfig,
len(rc.Registries))
+ for k, v := range rc.Registries {
+ registries[k] = v.Clone()
+ }
+ return registries
+}
+
+func (rc *InstanceOptions) CloneConfigCenter() *global.CenterConfig {
+ if rc.ConfigCenter == nil {
+ return nil
+ }
+ return rc.ConfigCenter.Clone()
+}
+
+func (rc *InstanceOptions) CloneMetadataReport() *global.MetadataReportConfig {
+ if rc.MetadataReport == nil {
+ return nil
+ }
+ return rc.MetadataReport.Clone()
+}
+
+func (rc *InstanceOptions) CloneProvider() *global.ProviderConfig {
+ if rc.Provider == nil {
+ return nil
+ }
+ return rc.Provider.Clone()
+}
+
+func (rc *InstanceOptions) CloneConsumer() *global.ConsumerConfig {
+ if rc.Consumer == nil {
+ return nil
+ }
+ return rc.Consumer.Clone()
+}
+
+func (rc *InstanceOptions) CloneMetrics() *global.MetricsConfig {
+ if rc.Metrics == nil {
+ return nil
+ }
+ return rc.Metrics.Clone()
+}
+
+func (rc *InstanceOptions) CloneOtel() *global.OtelConfig {
+ if rc.Otel == nil {
+ return nil
+ }
+ return rc.Otel.Clone()
+}
+
+func (rc *InstanceOptions) CloneLogger() *global.LoggerConfig {
+ if rc.Logger == nil {
+ return nil
+ }
+ return rc.Logger.Clone()
+}
+
+func (rc *InstanceOptions) CloneShutdown() *global.ShutdownConfig {
+ if rc.Shutdown == nil {
+ return nil
+ }
+ return rc.Shutdown.Clone()
+}
+
+func (rc *InstanceOptions) CloneCustom() *global.CustomConfig {
+ if rc.Custom == nil {
+ return nil
+ }
+ return rc.Custom.Clone()
+}
+
+func (rc *InstanceOptions) CloneProfiles() *global.ProfilesConfig {
+ if rc.Profiles == nil {
+ return nil
+ }
+ return rc.Profiles.Clone()
+}
+
+func (rc *InstanceOptions) CloneTLSConfig() *global.TLSConfig {
+ if rc.TLSConfig == nil {
+ return nil
+ }
+ return rc.TLSConfig.Clone()
+}
+
type InstanceOption func(*InstanceOptions)
func WithOrganization(organization string) InstanceOption {