Skip to content

Commit 05839d9

Browse files
PinZhangjoeyb
authored andcommitted
Fixed bug: The DiscoveryRequest with resource names may never be updated after xDS server is restarted with empty SnapshotCache. (#103)
Signed-off-by: Pin Zhang <[email protected]>
1 parent 450d0b3 commit 05839d9

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

cache/src/main/java/io/envoyproxy/controlplane/cache/SimpleCache.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,22 @@ public Watch createWatch(
145145
}
146146

147147
// Otherwise, the watch may be responded immediately
148-
respond(watch, snapshot, group);
148+
boolean responded = respond(watch, snapshot, group);
149+
150+
if (!responded) {
151+
watchCount++;
152+
153+
LOGGER.info("did not respond immediately, leaving open watch {} for {}[{}] from node {} for version {}",
154+
watchCount,
155+
request.getTypeUrl(),
156+
String.join(", ", request.getResourceNamesList()),
157+
group,
158+
request.getVersionInfo());
159+
160+
status.setWatch(watchCount, watch);
161+
162+
watch.setStop(() -> status.removeWatch(watchCount));
163+
}
149164

150165
return watch;
151166

@@ -245,7 +260,7 @@ private Response createResponse(DiscoveryRequest request, Map<String, ? extends
245260
return Response.create(request, filtered, version);
246261
}
247262

248-
private void respond(Watch watch, Snapshot snapshot, T group) {
263+
private boolean respond(Watch watch, Snapshot snapshot, T group) {
249264
Map<String, ? extends Message> snapshotResources = snapshot.resources(watch.request().getTypeUrl());
250265

251266
if (!watch.request().getResourceNamesList().isEmpty() && watch.ads()) {
@@ -262,7 +277,7 @@ private void respond(Watch watch, Snapshot snapshot, T group) {
262277
String.join(", ", watch.request().getResourceNamesList()),
263278
String.join(", ", missingNames));
264279

265-
return;
280+
return false;
266281
}
267282
}
268283

@@ -281,6 +296,7 @@ private void respond(Watch watch, Snapshot snapshot, T group) {
281296

282297
try {
283298
watch.respond(response);
299+
return true;
284300
} catch (WatchCancelledException e) {
285301
LOGGER.error(
286302
"failed to respond for {} from node {} at version {} with version {} because watch was already cancelled",
@@ -289,5 +305,7 @@ private void respond(Watch watch, Snapshot snapshot, T group) {
289305
watch.request().getVersionInfo(),
290306
version);
291307
}
308+
309+
return false;
292310
}
293311
}

cache/src/test/java/io/envoyproxy/controlplane/cache/SimpleCacheTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.envoyproxy.controlplane.cache;
22

3+
import static io.envoyproxy.controlplane.cache.Resources.ROUTE_TYPE_URL;
34
import static org.assertj.core.api.Assertions.assertThat;
45

56
import com.google.common.collect.ImmutableList;
@@ -350,6 +351,26 @@ public void watchesAreReleasedAfterCancel() {
350351
watches.values().forEach(w -> assertThat(w.watch.isCancelled()).isTrue());
351352
}
352353

354+
@Test
355+
public void watchIsLeftOpenIfNotRespondedImmediately() {
356+
SimpleCache<String> cache = new SimpleCache<>(new SingleNodeGroup());
357+
cache.setSnapshot(SingleNodeGroup.GROUP, Snapshot.create(
358+
ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), VERSION1));
359+
360+
ResponseTracker responseTracker = new ResponseTracker();
361+
Watch watch = cache.createWatch(
362+
true,
363+
DiscoveryRequest.newBuilder()
364+
.setNode(Node.getDefaultInstance())
365+
.setTypeUrl(ROUTE_TYPE_URL)
366+
.addAllResourceNames(Collections.singleton(ROUTE_NAME))
367+
.build(),
368+
Collections.singleton(ROUTE_NAME),
369+
responseTracker);
370+
371+
assertThatWatchIsOpenWithNoResponses(new WatchAndTracker(watch, responseTracker));
372+
}
373+
353374
@Test
354375
public void getSnapshot() {
355376
SimpleCache<String> cache = new SimpleCache<>(new SingleNodeGroup());

0 commit comments

Comments
 (0)