Fix goroutine leak in consulcatalog when consul is down

This commit is contained in:
yutopp 2018-03-20 22:36:03 +09:00 committed by Traefiker Bot
parent 7afa33dfa1
commit 43a510c046

View file

@ -6,6 +6,7 @@ import (
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"sync"
"text/template" "text/template"
"time" "time"
@ -135,7 +136,7 @@ func getChangedIntKeys(currState []int, prevState []int) ([]int, []int) {
return fun.Keys(addedKeys).([]int), fun.Keys(removedKeys).([]int) return fun.Keys(addedKeys).([]int), fun.Keys(removedKeys).([]int)
} }
func (p *CatalogProvider) watchHealthState(stopCh <-chan struct{}, watchCh chan<- map[string][]string, errorCh chan<- error) { func (p *CatalogProvider) watchHealthState(stopCh <-chan struct{}, watchCh chan<- map[string][]string, notifyError func(error)) {
health := p.client.Health() health := p.client.Health()
catalog := p.client.Catalog() catalog := p.client.Catalog()
@ -156,7 +157,7 @@ func (p *CatalogProvider) watchHealthState(stopCh <-chan struct{}, watchCh chan<
healthyState, meta, err := health.State("passing", options) healthyState, meta, err := health.State("passing", options)
if err != nil { if err != nil {
log.WithError(err).Error("Failed to retrieve health checks") log.WithError(err).Error("Failed to retrieve health checks")
errorCh <- err notifyError(err)
return return
} }
@ -180,7 +181,7 @@ func (p *CatalogProvider) watchHealthState(stopCh <-chan struct{}, watchCh chan<
data, _, err := catalog.Services(&api.QueryOptions{}) data, _, err := catalog.Services(&api.QueryOptions{})
if err != nil { if err != nil {
log.Errorf("Failed to list services: %s", err) log.Errorf("Failed to list services: %s", err)
errorCh <- err notifyError(err)
return return
} }
@ -214,7 +215,7 @@ type Service struct {
Ports []int Ports []int
} }
func (p *CatalogProvider) watchCatalogServices(stopCh <-chan struct{}, watchCh chan<- map[string][]string, errorCh chan<- error) { func (p *CatalogProvider) watchCatalogServices(stopCh <-chan struct{}, watchCh chan<- map[string][]string, notifyError func(error)) {
catalog := p.client.Catalog() catalog := p.client.Catalog()
safe.Go(func() { safe.Go(func() {
@ -233,7 +234,7 @@ func (p *CatalogProvider) watchCatalogServices(stopCh <-chan struct{}, watchCh c
data, meta, err := catalog.Services(options) data, meta, err := catalog.Services(options)
if err != nil { if err != nil {
log.Errorf("Failed to list services: %s", err) log.Errorf("Failed to list services: %s", err)
errorCh <- err notifyError(err)
return return
} }
@ -249,7 +250,7 @@ func (p *CatalogProvider) watchCatalogServices(stopCh <-chan struct{}, watchCh c
nodes, _, err := catalog.Service(key, "", &api.QueryOptions{}) nodes, _, err := catalog.Service(key, "", &api.QueryOptions{})
if err != nil { if err != nil {
log.Errorf("Failed to get detail of service %s: %s", key, err) log.Errorf("Failed to get detail of service %s: %s", key, err)
errorCh <- err notifyError(err)
return return
} }
nodesID := getServiceIds(nodes) nodesID := getServiceIds(nodes)
@ -572,8 +573,15 @@ func (p *CatalogProvider) watch(configurationChan chan<- types.ConfigMessage, st
watchCh := make(chan map[string][]string) watchCh := make(chan map[string][]string)
errorCh := make(chan error) errorCh := make(chan error)
p.watchHealthState(stopCh, watchCh, errorCh) var errorOnce sync.Once
p.watchCatalogServices(stopCh, watchCh, errorCh) notifyError := func(err error) {
errorOnce.Do(func() {
errorCh <- err
})
}
p.watchHealthState(stopCh, watchCh, notifyError)
p.watchCatalogServices(stopCh, watchCh, notifyError)
defer close(stopCh) defer close(stopCh)
defer close(watchCh) defer close(watchCh)