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

fix: 触发懒加载时,需要同步更新notify内容,更新component监听变更的ns #302

Merged
merged 8 commits into from Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 27 additions & 5 deletions client.go
Expand Up @@ -20,6 +20,7 @@ package agollo
import (
"container/list"
"errors"
"strings"

"github.com/apolloconfig/agollo/v4/agcache"
"github.com/apolloconfig/agollo/v4/agcache/memory"
Expand Down Expand Up @@ -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配置的缓存
Expand Down
31 changes: 27 additions & 4 deletions client_test.go
Expand Up @@ -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) {
Expand Down
18 changes: 18 additions & 0 deletions component/notify/componet_notify_test.go
Expand Up @@ -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"))
}
24 changes: 12 additions & 12 deletions env/config/config.go
Expand Up @@ -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"`
Expand All @@ -56,27 +56,27 @@ type AppConfig struct {
currentConnApolloConfig *CurrentApolloConfig
}

//ServerInfo 服务器信息
// ServerInfo 服务器信息
type ServerInfo struct {
AppName string `json:"appName"`
InstanceID string `json:"instanceId"`
HomepageURL string `json:"homepageUrl"`
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 {
Expand Down Expand Up @@ -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)
Expand All @@ -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(),
Expand Down