99 "fmt"
1010 "math"
1111 "net"
12+ "sort"
1213 "sync"
1314 "time"
1415
@@ -93,7 +94,14 @@ type ADSC struct {
9394 // Updates includes the type of the last update received from the server.
9495 Updates chan string
9596
96- mutex sync.Mutex
97+ mutex sync.Mutex
98+ watches map [string ]Watch
99+ }
100+
101+ type Watch struct {
102+ resources []string
103+ lastNonce string
104+ lastVersion string
97105}
98106
99107var (
@@ -106,6 +114,7 @@ func Dial(url string, opts *Config) (*ADSC, error) {
106114 adsc := & ADSC {
107115 done : make (chan error ),
108116 Updates : make (chan string , 100 ),
117+ watches : map [string ]Watch {},
109118 RootCert : opts .RootCert ,
110119 SystemCerts : opts .SystemCerts ,
111120 ClientCert : opts .ClientCert ,
@@ -249,7 +258,6 @@ func (a *ADSC) handleRecv() {
249258 }
250259 }
251260
252- // TODO: add hook to inject nacks
253261 a .mutex .Lock ()
254262 a .ack (msg , names )
255263 a .mutex .Unlock ()
@@ -292,6 +300,7 @@ func (a *ADSC) handleLDS(ll []*listener.Listener) {
292300 }
293301 }
294302 }
303+ sort .Strings (routes )
295304
296305 if dumpScope .DebugEnabled () {
297306 for i , l := range ll {
@@ -303,18 +312,41 @@ func (a *ADSC) handleLDS(ll []*listener.Listener) {
303312 dumpScope .Debugf ("lds %d: %v" , i , b )
304313 }
305314 }
315+
306316 a .mutex .Lock ()
307317 defer a .mutex .Unlock ()
308- if len (routes ) > 0 {
309- a .sendRequest (resource .RouteType , routes )
310- }
318+
319+ a .handleResourceUpdate (resource .RouteType , routes )
311320
312321 select {
313322 case a .Updates <- "lds" :
314323 default :
315324 }
316325}
317326
327+ func (a * ADSC ) handleResourceUpdate (typeUrl string , resources []string ) {
328+ if ! listEqual (a .watches [typeUrl ].resources , resources ) {
329+ scope .Debugf ("%v type resources changed: %v -> %v" , typeUrl , a .watches [typeUrl ].resources , resources )
330+ watch := a .watches [typeUrl ]
331+ watch .resources = resources
332+ a .watches [typeUrl ] = watch
333+ a .request (typeUrl , watch )
334+ }
335+ }
336+
337+ // listEqual checks that two lists contain all the same elements
338+ func listEqual (a []string , b []string ) bool {
339+ if len (a ) != len (b ) {
340+ return false
341+ }
342+ for i := range a {
343+ if a [i ] != b [i ] {
344+ return false
345+ }
346+ }
347+ return true
348+ }
349+
318350// compact representations, for simplified debugging/testing
319351
320352// TCPListener extracts the core elements from envoy Listener.
@@ -355,10 +387,10 @@ func (a *ADSC) handleCDS(ll []*cluster.Cluster) {
355387
356388 cn = append (cn , c .Name )
357389 }
390+ sort .Strings (cn )
391+
392+ a .handleResourceUpdate (resource .EndpointType , cn )
358393
359- if len (cn ) > 0 {
360- a .sendRequest (resource .EndpointType , cn )
361- }
362394 if dumpScope .DebugEnabled () {
363395 for i , c := range ll {
364396 b , err := marshal .MarshalToString (c )
@@ -372,6 +404,14 @@ func (a *ADSC) handleCDS(ll []*cluster.Cluster) {
372404
373405 a .mutex .Lock ()
374406 defer a .mutex .Unlock ()
407+ if ! a .InitialLoad {
408+ // first load - Envoy loads listeners after endpoints
409+ _ = a .send (& discovery.DiscoveryRequest {
410+ Node : a .node ,
411+ TypeUrl : resource .ListenerType ,
412+ }, ReasonInit )
413+ a .InitialLoad = true
414+ }
375415
376416 select {
377417 case a .Updates <- "cds" :
@@ -410,13 +450,6 @@ func (a *ADSC) handleEDS(eds []*endpoint.ClusterLoadAssignment) {
410450 dumpScope .Debugf ("eds %d: %v" , i , b )
411451 }
412452 }
413- if ! a .InitialLoad {
414- // first load - Envoy loads listeners after endpoints
415- _ = a .send (& discovery.DiscoveryRequest {
416- Node : a .node ,
417- TypeUrl : resource .ListenerType ,
418- }, "init" )
419- }
420453
421454 a .mutex .Lock ()
422455 defer a .mutex .Unlock ()
@@ -435,10 +468,6 @@ func (a *ADSC) handleRDS(configurations []*route.RouteConfiguration) {
435468 rds [r .Name ] = r
436469 }
437470
438- if ! a .InitialLoad {
439- a .InitialLoad = true
440- }
441-
442471 if dumpScope .DebugEnabled () {
443472 for i , r := range configurations {
444473 b , err := marshal .MarshalToString (r )
@@ -496,28 +525,38 @@ func (a *ADSC) Watch() {
496525 err := a .send (& discovery.DiscoveryRequest {
497526 Node : a .node ,
498527 TypeUrl : resource .ClusterType ,
499- }, "init" )
528+ }, ReasonInit )
500529 if err != nil {
501530 scope .Errorf ("Error sending request: %v" , err )
502531 }
503532}
504533
505- func (a * ADSC ) sendRequest (typeurl string , rsc []string ) {
534+ const (
535+ ReasonAck = "ack"
536+ ReasonRequest = "request"
537+ ReasonInit = "init"
538+ )
539+
540+ func (a * ADSC ) request (typeUrl string , watch Watch ) {
506541 _ = a .send (& discovery.DiscoveryRequest {
507- ResponseNonce : "" ,
542+ ResponseNonce : watch .lastNonce ,
543+ TypeUrl : typeUrl ,
508544 Node : a .node ,
509- TypeUrl : typeurl ,
510- ResourceNames : rsc ,
511- }, "request" )
545+ VersionInfo : watch . lastVersion ,
546+ ResourceNames : watch . resources ,
547+ }, ReasonRequest )
512548}
513549
514550func (a * ADSC ) ack (msg * discovery.DiscoveryResponse , names []string ) {
515- sendNames := names
551+ watch := a .watches [msg .TypeUrl ]
552+ watch .lastNonce = msg .Nonce
553+ watch .lastVersion = msg .VersionInfo
554+ a .watches [msg .TypeUrl ] = watch
516555 _ = a .send (& discovery.DiscoveryRequest {
517556 ResponseNonce : msg .Nonce ,
518557 TypeUrl : msg .TypeUrl ,
519558 Node : a .node ,
520559 VersionInfo : msg .VersionInfo ,
521- ResourceNames : sendNames ,
522- }, "ack" )
560+ ResourceNames : names ,
561+ }, ReasonAck )
523562}
0 commit comments