xds:fix cancel xds watcher accidentally removes the url (#9809)

Fix a bug. When any of the xds subscribers for a resource has the last watcher cancelled, the bug will accidentally remove that resource type from the map, which make xds stream not accepting response update for that resource type entirely(pass through, no ACK/NACK will send).
This commit is contained in:
yifeizhuang 2023-01-11 15:33:48 -08:00 committed by GitHub
parent eb391fd66c
commit 82ca98f338
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 1 deletions

View File

@ -332,12 +332,13 @@ final class XdsClientImpl extends XdsClient
if (!subscriber.isWatched()) {
subscriber.cancelResourceWatch();
resourceSubscribers.get(type).remove(resourceName);
subscribedResourceTypeUrls.remove(type.typeUrl());
if (subscriber.xdsChannel != null) {
subscriber.xdsChannel.adjustResourceSubscription(type);
}
if (resourceSubscribers.get(type).isEmpty()) {
resourceSubscribers.remove(type);
subscribedResourceTypeUrls.remove(type.typeUrl());
}
}
}

View File

@ -938,6 +938,35 @@ public abstract class XdsClientImplTestBase {
assertThat(channelForEmptyAuthority).isNull();
}
@Test
public void cancelResourceWatcherNotRemoveUrlSubscribers() {
DiscoveryRpcCall call = startResourceWatcher(XdsListenerResource.getInstance(), LDS_RESOURCE,
ldsResourceWatcher);
verifyResourceMetadataRequested(LDS, LDS_RESOURCE);
// Initial LDS response.
call.sendResponse(LDS, testListenerVhosts, VERSION_1, "0000");
call.verifyRequest(LDS, LDS_RESOURCE, VERSION_1, "0000", NODE);
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
verifyGoldenListenerVhosts(ldsUpdateCaptor.getValue());
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerVhosts, VERSION_1, TIME_INCREMENT);
xdsClient.watchXdsResource(XdsListenerResource.getInstance(),
LDS_RESOURCE + "1", ldsResourceWatcher);
xdsClient.cancelXdsResourceWatch(XdsListenerResource.getInstance(), LDS_RESOURCE + "1",
ldsResourceWatcher);
// Updated LDS response.
Any testListenerVhosts2 = Any.pack(mf.buildListenerWithApiListener(LDS_RESOURCE,
mf.buildRouteConfiguration("new", mf.buildOpaqueVirtualHosts(VHOST_SIZE))));
call.sendResponse(LDS, testListenerVhosts2, VERSION_2, "0001");
call.verifyRequest(LDS, LDS_RESOURCE, VERSION_2, "0001", NODE);
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
verifyGoldenListenerVhosts(ldsUpdateCaptor.getValue());
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerVhosts2, VERSION_2,
TIME_INCREMENT * 2);
}
@Test
public void ldsResourceUpdated_withXdstpResourceName() {
BootstrapperImpl.enableFederation = true;