@@ -27,18 +27,24 @@ type discoveryReloader interface {
2727 discovery.Watcher
2828 Stop ()
2929 Reload (backend , address string , clusterOpts map [string ]string ) error
30+ ReadyCh () <- chan struct {}
3031}
3132
3233type daemonDiscoveryReloader struct {
3334 backend discovery.Backend
3435 ticker * time.Ticker
3536 term chan bool
37+ readyCh chan struct {}
3638}
3739
3840func (d * daemonDiscoveryReloader ) Watch (stopCh <- chan struct {}) (<- chan discovery.Entries , <- chan error ) {
3941 return d .backend .Watch (stopCh )
4042}
4143
44+ func (d * daemonDiscoveryReloader ) ReadyCh () <- chan struct {} {
45+ return d .readyCh
46+ }
47+
4248func discoveryOpts (clusterOpts map [string ]string ) (time.Duration , time.Duration , error ) {
4349 var (
4450 heartbeat = defaultDiscoveryHeartbeat
@@ -87,38 +93,64 @@ func initDiscovery(backendAddress, advertiseAddress string, clusterOpts map[stri
8793 backend : backend ,
8894 ticker : time .NewTicker (heartbeat ),
8995 term : make (chan bool ),
96+ readyCh : make (chan struct {}),
9097 }
9198 // We call Register() on the discovery backend in a loop for the whole lifetime of the daemon,
9299 // but we never actually Watch() for nodes appearing and disappearing for the moment.
93- reloader .advertise (advertiseAddress )
100+ go reloader .advertiseHeartbeat (advertiseAddress )
94101 return reloader , nil
95102}
96103
97- func (d * daemonDiscoveryReloader ) advertise (address string ) {
98- d .registerAddr (address )
99- go d .advertiseHeartbeat (address )
100- }
101-
102- func (d * daemonDiscoveryReloader ) registerAddr (addr string ) {
103- if err := d .backend .Register (addr ); err != nil {
104- log .Warnf ("Registering as %q in discovery failed: %v" , addr , err )
105- }
106- }
107-
108104// advertiseHeartbeat registers the current node against the discovery backend using the specified
109105// address. The function never returns, as registration against the backend comes with a TTL and
110106// requires regular heartbeats.
111107func (d * daemonDiscoveryReloader ) advertiseHeartbeat (address string ) {
108+ var ready bool
109+ if err := d .initHeartbeat (address ); err == nil {
110+ ready = true
111+ close (d .readyCh )
112+ }
113+
112114 for {
113115 select {
114116 case <- d .ticker .C :
115- d .registerAddr (address )
117+ if err := d .backend .Register (address ); err != nil {
118+ log .Warnf ("Registering as %q in discovery failed: %v" , address , err )
119+ } else {
120+ if ! ready {
121+ close (d .readyCh )
122+ ready = true
123+ }
124+ }
116125 case <- d .term :
117126 return
118127 }
119128 }
120129}
121130
131+ // initHeartbeat is used to do the first heartbeat. It uses a tight loop until
132+ // either the timeout period is reached or the heartbeat is successful and returns.
133+ func (d * daemonDiscoveryReloader ) initHeartbeat (address string ) error {
134+ // Setup a short ticker until the first heartbeat has succeeded
135+ t := time .NewTicker (500 * time .Millisecond )
136+ defer t .Stop ()
137+ // timeout makes sure that after a period of time we stop being so aggressive trying to reach the discovery service
138+ timeout := time .After (60 * time .Second )
139+
140+ for {
141+ select {
142+ case <- timeout :
143+ return errors .New ("timeout waiting for initial discovery" )
144+ case <- d .term :
145+ return errors .New ("terminated" )
146+ case <- t .C :
147+ if err := d .backend .Register (address ); err == nil {
148+ return nil
149+ }
150+ }
151+ }
152+ }
153+
122154// Reload makes the watcher to stop advertising and reconfigures it to advertise in a new address.
123155func (d * daemonDiscoveryReloader ) Reload (backendAddress , advertiseAddress string , clusterOpts map [string ]string ) error {
124156 d .Stop ()
@@ -130,8 +162,9 @@ func (d *daemonDiscoveryReloader) Reload(backendAddress, advertiseAddress string
130162
131163 d .backend = backend
132164 d .ticker = time .NewTicker (heartbeat )
165+ d .readyCh = make (chan struct {})
133166
134- d . advertise (advertiseAddress )
167+ go d . advertiseHeartbeat (advertiseAddress )
135168 return nil
136169}
137170
0 commit comments