diff --git a/client.go b/client.go index c2b8ecb6..5f2d6e5a 100644 --- a/client.go +++ b/client.go @@ -20,6 +20,7 @@ package agollo import ( "container/list" "errors" + "strings" "github.com/apolloconfig/agollo/v4/agcache" "github.com/apolloconfig/agollo/v4/agcache/memory" @@ -158,19 +159,40 @@ func (c *internalClient) GetConfigAndInit(namespace string) *storage.Config { return nil } - config := c.cache.GetConfig(namespace) + cfg := c.cache.GetConfig(namespace) - if config == nil { + if cfg == nil { //sync config apolloConfig := syncApolloConfig.SyncWithNamespace(namespace, c.getAppConfig) if apolloConfig != nil { - c.cache.UpdateApolloConfig(apolloConfig, c.getAppConfig) + c.SyncAndUpdate(namespace, apolloConfig) + } + } + + cfg = c.cache.GetConfig(namespace) + + return cfg +} + +func (c *internalClient) SyncAndUpdate(namespace string, apolloConfig *config.ApolloConfig) { + // update appConfig only if namespace does not exist yet + namespaces := strings.Split(c.appConfig.NamespaceName, ",") + exists := false + for _, n := range namespaces { + if n == namespace { + exists = true + break } } + if !exists { + c.appConfig.NamespaceName += "," + namespace + } - config = c.cache.GetConfig(namespace) + // update notification + c.appConfig.GetNotificationsMap().UpdateNotify(namespace, 0) - return config + // update cache + c.cache.UpdateApolloConfig(apolloConfig, c.getAppConfig) } // GetConfigCache 根据namespace获取apollo配置的缓存 diff --git a/client_test.go b/client_test.go index 41ffc31d..8a2d7d00 100644 --- a/client_test.go +++ b/client_test.go @@ -365,17 +365,40 @@ func TestGetConfigAndInitValNotNil(t *testing.T) { AppID: "testID", NamespaceName: "testNotFound", }, - Configurations: map[string]interface{}{"testKey": "testValue"}, + Configurations: map[string]interface{}{"testKey": "testUpdatedValue"}, } }) - defer patch.Reset() client := createMockApolloConfig(120) cf := client.GetConfig("testNotFound") Assert(t, cf, NotNilVal()) - // cache should be updated + + // appConfig notificationsMap appConfig should be updated + Assert(t, client.appConfig.GetNotificationsMap().GetNotify("testNotFound"), Equal(int64(0))) + + // cache should be updated with new configuration Assert(t, client.cache.GetConfig("testNotFound"), NotNilVal()) - Assert(t, client.cache.GetConfig("testNotFound").GetValue("testKey"), Equal("testValue")) + Assert(t, client.cache.GetConfig("testNotFound").GetValue("testKey"), Equal("testUpdatedValue")) + Assert(t, client.appConfig.NamespaceName, Equal("application,testNotFound")) + patch.Reset() + + // second replace + patch1 := gomonkey.ApplyMethod(reflect.TypeOf(apc), "SyncWithNamespace", func(_ *remote.AbsApolloConfig, namespace string, appConfigFunc func() config.AppConfig) *config.ApolloConfig { + return &config.ApolloConfig{ + ApolloConnConfig: config.ApolloConnConfig{ + AppID: "testID", + NamespaceName: "testNotFound1", + }, + Configurations: map[string]interface{}{"testKey": "testUpdatedValue"}, + } + }) + defer patch1.Reset() + client.appConfig.NamespaceName = "testNotFound1" + cf1 := client.GetConfig("testNotFound1") + Assert(t, cf1, NotNilVal()) + Assert(t, client.cache.GetConfig("testNotFound1"), NotNilVal()) + // appConfig namespace existed, should not be appended + Assert(t, client.appConfig.NamespaceName, Equal("testNotFound1")) } func TestGetConfigAndInitValNil(t *testing.T) { diff --git a/component/notify/componet_notify_test.go b/component/notify/componet_notify_test.go index ec3b04a6..bb5c4efc 100644 --- a/component/notify/componet_notify_test.go +++ b/component/notify/componet_notify_test.go @@ -102,3 +102,21 @@ func getTestAppConfig() *config.AppConfig { appConfig.Init() return appConfig } + +func TestConfigComponent_SetAppConfig_UpdatesAppConfigCorrectly(t *testing.T) { + expectedAppConfig := getTestAppConfig() + c := &ConfigComponent{} + // set appConfigFunc + c.SetAppConfig(func() config.AppConfig { + return *expectedAppConfig + }) + + // appConfig should be equal + Assert(t, c.appConfigFunc(), Equal(*expectedAppConfig)) + + // appConfig value is be replaced + expectedAppConfig.AppID = "test1" + expectedAppConfig.NamespaceName = expectedAppConfig.NamespaceName + config.Comma + "abc" + Assert(t, c.appConfigFunc().AppID, Equal("test1")) + Assert(t, c.appConfigFunc().NamespaceName, Equal("application,abc")) +} diff --git a/env/config/config.go b/env/config/config.go index cea37e49..ebfde508 100644 --- a/env/config/config.go +++ b/env/config/config.go @@ -29,17 +29,17 @@ import ( var ( defaultNotificationID = int64(-1) - comma = "," + Comma = "," ) -//File 读写配置文件 +// File 读写配置文件 type File interface { Load(fileName string, unmarshal func([]byte) (interface{}, error)) (interface{}, error) Write(content interface{}, configPath string) error } -//AppConfig 配置文件 +// AppConfig 配置文件 type AppConfig struct { AppID string `json:"appId"` Cluster string `json:"cluster"` @@ -56,7 +56,7 @@ type AppConfig struct { currentConnApolloConfig *CurrentApolloConfig } -//ServerInfo 服务器信息 +// ServerInfo 服务器信息 type ServerInfo struct { AppName string `json:"appName"` InstanceID string `json:"instanceId"` @@ -64,19 +64,19 @@ type ServerInfo struct { IsDown bool `json:"-"` } -//GetIsBackupConfig whether backup config after fetch config from apollo -//false : no -//true : yes (default) +// GetIsBackupConfig whether backup config after fetch config from apollo +// false : no +// true : yes (default) func (a *AppConfig) GetIsBackupConfig() bool { return a.IsBackupConfig } -//GetBackupConfigPath GetBackupConfigPath +// GetBackupConfigPath GetBackupConfigPath func (a *AppConfig) GetBackupConfigPath() string { return a.BackupConfigPath } -//GetHost GetHost +// GetHost GetHost func (a *AppConfig) GetHost() string { u, err := url.Parse(a.IP) if err != nil { @@ -108,10 +108,10 @@ func (a *AppConfig) initAllNotifications(callback func(namespace string)) { } } -//SplitNamespaces 根据namespace字符串分割后,并执行callback函数 +// SplitNamespaces 根据namespace字符串分割后,并执行callback函数 func SplitNamespaces(namespacesStr string, callback func(namespace string)) sync.Map { namespaces := sync.Map{} - split := strings.Split(namespacesStr, comma) + split := strings.Split(namespacesStr, Comma) for _, namespace := range split { if callback != nil { callback(namespace) @@ -126,7 +126,7 @@ func (a *AppConfig) GetNotificationsMap() *notificationsMap { return a.notificationsMap } -//GetServicesConfigURL 获取服务器列表url +// GetServicesConfigURL 获取服务器列表url func (a *AppConfig) GetServicesConfigURL() string { return fmt.Sprintf("%sservices/config?appId=%s&ip=%s", a.GetHost(),