优化结构
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
package runtimeconfig
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -41,6 +42,13 @@ func cloneConfig(config Config) Config {
|
||||
return config
|
||||
}
|
||||
|
||||
func sameConfig(left, right Config) bool {
|
||||
return left.Kind == right.Kind &&
|
||||
left.Provider == right.Provider &&
|
||||
left.Enabled == right.Enabled &&
|
||||
bytes.Equal(left.Values, right.Values)
|
||||
}
|
||||
|
||||
func (s *Store) Get(kind, provider string) (Config, bool) {
|
||||
if s == nil {
|
||||
return Config{}, false
|
||||
@@ -105,11 +113,20 @@ func (s *Store) Replace(configs []Config) {
|
||||
s.mu.Unlock()
|
||||
|
||||
changed := make(map[string]Config, len(previous)+len(next))
|
||||
for key, config := range previous {
|
||||
changed[key] = Config{Kind: config.Kind, Provider: config.Provider}
|
||||
for key, previousConfig := range previous {
|
||||
nextConfig, exists := next[key]
|
||||
if !exists {
|
||||
changed[key] = Config{Kind: previousConfig.Kind, Provider: previousConfig.Provider}
|
||||
continue
|
||||
}
|
||||
if !sameConfig(previousConfig, nextConfig) {
|
||||
changed[key] = nextConfig
|
||||
}
|
||||
}
|
||||
for key, config := range next {
|
||||
changed[key] = config
|
||||
for key, nextConfig := range next {
|
||||
if _, exists := previous[key]; !exists {
|
||||
changed[key] = nextConfig
|
||||
}
|
||||
}
|
||||
for _, item := range listeners {
|
||||
if config, ok := changed[configKey(item.kind, item.provider)]; ok {
|
||||
|
||||
@@ -3,6 +3,7 @@ package runtimeconfig
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestStoreSetDeleteAndSubscribe(t *testing.T) {
|
||||
@@ -28,3 +29,37 @@ func TestStoreSetDeleteAndSubscribe(t *testing.T) {
|
||||
t.Fatalf("delete update = %#v", update)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreReplaceSkipsUnchangedValues(t *testing.T) {
|
||||
store := NewStore()
|
||||
updates := make(chan Config, 2)
|
||||
stop := store.Subscribe("mq", "rabbitmq", func(config Config) { updates <- config })
|
||||
defer stop()
|
||||
|
||||
config := Config{Kind: "mq", Provider: "rabbitmq", Enabled: true, Values: json.RawMessage(`{"host":"localhost"}`)}
|
||||
store.Set(config)
|
||||
select {
|
||||
case <-updates:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("initial set notification was not delivered")
|
||||
}
|
||||
|
||||
store.Replace([]Config{config})
|
||||
select {
|
||||
case update := <-updates:
|
||||
t.Fatalf("unchanged replace emitted notification: %#v", update)
|
||||
case <-time.After(20 * time.Millisecond):
|
||||
}
|
||||
|
||||
changed := config
|
||||
changed.Values = json.RawMessage(`{"host":"other"}`)
|
||||
store.Replace([]Config{changed})
|
||||
select {
|
||||
case update := <-updates:
|
||||
if string(update.Values) != string(changed.Values) {
|
||||
t.Fatalf("changed replace = %#v", update)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("changed replace notification was not delivered")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user