Don't throw away valid configuration updates

This commit is contained in:
Andrew Parker 2020-02-10 20:40:06 +00:00 committed by GitHub
parent 8bb625adb7
commit 6e43ab5897
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 7 deletions

View file

@ -143,8 +143,6 @@ func (c *ConfigurationWatcher) loadMessage(configMsg dynamic.Message) {
}
func (c *ConfigurationWatcher) preLoadConfiguration(configMsg dynamic.Message) {
currentConfigurations := c.currentConfigurations.Get().(dynamic.Configurations)
logger := log.WithoutContext().WithField(log.ProviderName, configMsg.ProviderName)
if log.GetLevel() == logrus.DebugLevel {
copyConf := configMsg.Configuration.DeepCopy()
@ -172,11 +170,6 @@ func (c *ConfigurationWatcher) preLoadConfiguration(configMsg dynamic.Message) {
return
}
if reflect.DeepEqual(currentConfigurations[configMsg.ProviderName], configMsg.Configuration) {
logger.Infof("Skipping same configuration for provider %s", configMsg.ProviderName)
return
}
providerConfigUpdateCh, ok := c.providerConfigUpdateMap[configMsg.ProviderName]
if !ok {
providerConfigUpdateCh = make(chan dynamic.Message)
@ -211,11 +204,18 @@ func (c *ConfigurationWatcher) throttleProviderConfigReload(ctx context.Context,
}
})
var previousConfig dynamic.Message
for {
select {
case <-ctx.Done():
return
case nextConfig := <-in:
if reflect.DeepEqual(previousConfig, nextConfig) {
logger := log.WithoutContext().WithField(log.ProviderName, nextConfig.ProviderName)
logger.Info("Skipping same configuration")
continue
}
previousConfig = nextConfig
ring.In() <- nextConfig
}
}

View file

@ -175,6 +175,66 @@ func TestListenProvidersSkipsSameConfigurationForProvider(t *testing.T) {
time.Sleep(100 * time.Millisecond)
}
func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) {
routinesPool := safe.NewPool(context.Background())
configuration := &dynamic.Configuration{
HTTP: th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo")),
th.WithLoadBalancerServices(th.WithService("bar")),
),
}
transientConfiguration := &dynamic.Configuration{
HTTP: th.BuildConfiguration(
th.WithRouters(th.WithRouter("bad")),
th.WithLoadBalancerServices(th.WithService("bad")),
),
}
pvd := &mockProvider{
wait: 5 * time.Millisecond, // The last message needs to be received before the second has been fully processed
messages: []dynamic.Message{
{ProviderName: "mock", Configuration: configuration},
{ProviderName: "mock", Configuration: transientConfiguration},
{ProviderName: "mock", Configuration: configuration},
},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, 15*time.Millisecond)
var lastConfig dynamic.Configuration
watcher.AddListener(func(conf dynamic.Configuration) {
lastConfig = conf
})
watcher.Start()
defer watcher.Stop()
// give some time so that the configuration can be processed
time.Sleep(40 * time.Millisecond)
expected := dynamic.Configuration{
HTTP: th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo@mock")),
th.WithLoadBalancerServices(th.WithService("bar@mock")),
th.WithMiddlewares(),
),
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Services: map[string]*dynamic.TCPService{},
},
TLS: &dynamic.TLSConfiguration{
Options: map[string]tls.Options{
"default": {},
},
Stores: map[string]tls.Store{},
},
}
assert.Equal(t, expected, lastConfig)
}
func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) {
routinesPool := safe.NewPool(context.Background())