@@ -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
}
@@ -141,11 +147,25 @@ func (cache *LinearCache) notifyAll(modified map[string]struct{}) {
141
147
// de-duplicate watches that need to be responded
142
148
notifyList := make (map [chan Response ][]string )
143
149
for name := range modified {
144
- for watch := range cache .watches [name ] {
145
- notifyList [watch ] = append (notifyList [watch ], name )
150
+ for watch , streamState := range cache .watches [name ] {
151
+ resourceNames := streamState .GetKnownResourceNames (cache .typeURL )
152
+ modifiedNameInResourceName := false
153
+ for resourceName := range resourceNames {
154
+ if ! modifiedNameInResourceName && resourceName == name {
155
+ modifiedNameInResourceName = true
156
+ }
157
+ // To avoid the stale in notifyList becomes empty slice.
158
+ // Don't skip resource name that has been deleted here.
159
+ // It would be filtered out in respond because the corresponding resource has been deleted.
160
+ notifyList [watch ] = append (notifyList [watch ], resourceName )
161
+ }
162
+ if ! modifiedNameInResourceName {
163
+ notifyList [watch ] = append (notifyList [watch ], name )
164
+ }
146
165
}
147
166
delete (cache .watches , name )
148
167
}
168
+
149
169
for value , stale := range notifyList {
150
170
cache .respond (value , stale )
151
171
}
@@ -293,10 +313,16 @@ func (cache *LinearCache) CreateWatch(request *Request, streamState stream.Strea
293
313
stale = lastVersion != cache .version
294
314
} else {
295
315
for _ , name := range request .ResourceNames {
316
+ _ , has := streamState .GetKnownResourceNames (request .TypeUrl )[name ]
317
+ version , exists := cache .versionVector [name ]
318
+
296
319
// When a resource is removed, its version defaults 0 and it is not considered stale.
297
- if lastVersion < cache . versionVector [ name ] {
320
+ if lastVersion < version || ( ! has && exists ) {
298
321
stale = true
299
- staleResources = append (staleResources , name )
322
+
323
+ // Here we collect all requested names.
324
+ // It would be filtered out in respond if the resource name doesn't appear in cache.
325
+ staleResources = request .ResourceNames
300
326
}
301
327
}
302
328
}
@@ -306,7 +332,7 @@ func (cache *LinearCache) CreateWatch(request *Request, streamState stream.Strea
306
332
}
307
333
// Create open watches since versions are up to date.
308
334
if len (request .ResourceNames ) == 0 {
309
- cache .watchAll [value ] = struct {}{}
335
+ cache .watchAll [value ] = streamState
310
336
return func () {
311
337
cache .mu .Lock ()
312
338
defer cache .mu .Unlock ()
@@ -319,7 +345,7 @@ func (cache *LinearCache) CreateWatch(request *Request, streamState stream.Strea
319
345
set = make (watches )
320
346
cache .watches [name ] = set
321
347
}
322
- set [value ] = struct {}{}
348
+ set [value ] = streamState
323
349
}
324
350
return func () {
325
351
cache .mu .Lock ()
0 commit comments