Skip to content

Commit

Permalink
Don't throw away valid configuration updates
Browse files Browse the repository at this point in the history
  • Loading branch information
zaphod42 committed Feb 10, 2020
1 parent 8bb625a commit 6e43ab5
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 7 deletions.
14 changes: 7 additions & 7 deletions pkg/server/configurationwatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
}
}
Expand Down
60 changes: 60 additions & 0 deletions pkg/server/configurationwatcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())

Expand Down

0 comments on commit 6e43ab5

Please sign in to comment.