@@ -27,7 +27,7 @@ import (
27
27
"github.com/envoyproxy/go-control-plane/pkg/server/stream/v3"
28
28
)
29
29
30
- type watches = map [chan Response ]struct {}
30
+ type watches = map [chan Response ]stream. StreamState
31
31
32
32
// LinearCache supports collections of opaque resources. This cache has a
33
33
// single collection indexed by resource names and manages resource versions
@@ -114,24 +114,30 @@ func NewLinearCache(typeURL string, opts ...LinearCacheOption) *LinearCache {
114
114
}
115
115
116
116
func (cache * LinearCache ) respond (value chan Response , staleResources []string ) {
117
- var resources []types.ResourceWithTTL
117
+ var (
118
+ resources []types.ResourceWithTTL
119
+ respondResourceNames []string
120
+ )
121
+
118
122
// TODO: optimize the resources slice creations across different clients
119
123
if len (staleResources ) == 0 {
120
124
resources = make ([]types.ResourceWithTTL , 0 , len (cache .resources ))
121
- for _ , resource := range cache .resources {
125
+ for name , resource := range cache .resources {
122
126
resources = append (resources , types.ResourceWithTTL {Resource : resource })
127
+ respondResourceNames = append (respondResourceNames , name )
123
128
}
124
129
} else {
125
130
resources = make ([]types.ResourceWithTTL , 0 , len (staleResources ))
126
131
for _ , name := range staleResources {
127
132
resource := cache .resources [name ]
128
133
if resource != nil {
129
134
resources = append (resources , types.ResourceWithTTL {Resource : resource })
135
+ respondResourceNames = append (respondResourceNames , name )
130
136
}
131
137
}
132
138
}
133
139
value <- & RawResponse {
134
- Request : & Request {TypeUrl : cache .typeURL },
140
+ Request : & Request {TypeUrl : cache .typeURL , ResourceNames : respondResourceNames },
135
141
Resources : resources ,
136
142
Version : cache .getVersion (),
137
143
Ctx : context .Background (),
@@ -142,11 +148,25 @@ func (cache *LinearCache) notifyAll(modified map[string]struct{}) {
142
148
// de-duplicate watches that need to be responded
143
149
notifyList := make (map [chan Response ][]string )
144
150
for name := range modified {
145
- for watch := range cache .watches [name ] {
146
- notifyList [watch ] = append (notifyList [watch ], name )
151
+ for watch , streamState := range cache .watches [name ] {
152
+ resourceNames := streamState .GetKnownResourceNames (cache .typeURL )
153
+ modifiedNameInResourceName := false
154
+ for resourceName := range resourceNames {
155
+ if ! modifiedNameInResourceName && resourceName == name {
156
+ modifiedNameInResourceName = true
157
+ }
158
+ // To avoid the stale in notifyList becomes empty slice.
159
+ // Don't skip resource name that has been deleted here.
160
+ // It would be filtered out in respond because the corresponding resource has been deleted.
161
+ notifyList [watch ] = append (notifyList [watch ], resourceName )
162
+ }
163
+ if ! modifiedNameInResourceName {
164
+ notifyList [watch ] = append (notifyList [watch ], name )
165
+ }
147
166
}
148
167
delete (cache .watches , name )
149
168
}
169
+
150
170
for value , stale := range notifyList {
151
171
cache .respond (value , stale )
152
172
}
@@ -328,10 +348,16 @@ func (cache *LinearCache) CreateWatch(request *Request, streamState stream.Strea
328
348
stale = lastVersion != cache .version
329
349
} else {
330
350
for _ , name := range request .ResourceNames {
351
+ _ , has := streamState .GetKnownResourceNames (request .TypeUrl )[name ]
352
+ version , exists := cache .versionVector [name ]
353
+
331
354
// When a resource is removed, its version defaults 0 and it is not considered stale.
332
- if lastVersion < cache . versionVector [ name ] {
355
+ if lastVersion < version || ( ! has && exists ) {
333
356
stale = true
334
- staleResources = append (staleResources , name )
357
+
358
+ // Here we collect all requested names.
359
+ // It would be filtered out in respond if the resource name doesn't appear in cache.
360
+ staleResources = request .ResourceNames
335
361
}
336
362
}
337
363
}
@@ -341,7 +367,7 @@ func (cache *LinearCache) CreateWatch(request *Request, streamState stream.Strea
341
367
}
342
368
// Create open watches since versions are up to date.
343
369
if len (request .ResourceNames ) == 0 {
344
- cache .watchAll [value ] = struct {}{}
370
+ cache .watchAll [value ] = streamState
345
371
return func () {
346
372
cache .mu .Lock ()
347
373
defer cache .mu .Unlock ()
@@ -354,7 +380,7 @@ func (cache *LinearCache) CreateWatch(request *Request, streamState stream.Strea
354
380
set = make (watches )
355
381
cache .watches [name ] = set
356
382
}
357
- set [value ] = struct {}{}
383
+ set [value ] = streamState
358
384
}
359
385
return func () {
360
386
cache .mu .Lock ()
0 commit comments