Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

grpc-js-xds: Implement ignore_resource_deletion option #2198

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/grpc-js-xds/src/xds-client.ts
Expand Up @@ -360,6 +360,10 @@ export class XdsClient {
} else {
this.apiVersion = XdsApiVersion.V2;
}
if (bootstrapInfo.xdsServers[0].serverFeatures.indexOf('ignore_resource_deletion') >= 0) {
this.adsState.lds.enableIgnoreResourceDeletion();
this.adsState.cds.enableIgnoreResourceDeletion();
}
const nodeV2: NodeV2 = {
...bootstrapInfo.node,
build_version: `gRPC Node Pure JS ${clientVersion}`,
Expand Down
32 changes: 27 additions & 5 deletions packages/grpc-js-xds/src/xds-stream-state/xds-stream-state.ts
Expand Up @@ -75,6 +75,7 @@ interface SubscriptionEntry<ResponseType> {
watchers: Watcher<ResponseType>[];
cachedResponse: ResponseType | null;
resourceTimer: NodeJS.Timer;
deletionIgnored: boolean;
}

const RESOURCE_TIMEOUT_MS = 15_000;
Expand All @@ -86,6 +87,7 @@ export abstract class BaseXdsStreamState<ResponseType> implements XdsStreamState
private subscriptions: Map<string, SubscriptionEntry<ResponseType>> = new Map<string, SubscriptionEntry<ResponseType>>();
private latestIsV2 = false;
private isAdsStreamRunning = false;
private ignoreResourceDeletion = false;

constructor(private updateResourceNames: () => void) {}

Expand All @@ -111,7 +113,8 @@ export abstract class BaseXdsStreamState<ResponseType> implements XdsStreamState
subscriptionEntry = {
watchers: [],
cachedResponse: null,
resourceTimer: setTimeout(() => {}, 0)
resourceTimer: setTimeout(() => {}, 0),
deletionIgnored: false
};
if (this.isAdsStreamRunning) {
this.startResourceTimer(subscriptionEntry);
Expand Down Expand Up @@ -142,6 +145,9 @@ export abstract class BaseXdsStreamState<ResponseType> implements XdsStreamState
}
if (subscriptionEntry.watchers.length === 0) {
clearTimeout(subscriptionEntry.resourceTimer);
if (subscriptionEntry.deletionIgnored) {
experimental.log(logVerbosity.INFO, 'Unsubscribing from resource with previously ignored deletion: ' + resourceName);
}
this.subscriptions.delete(resourceName);
this.updateResourceNames();
}
Expand Down Expand Up @@ -187,6 +193,10 @@ export abstract class BaseXdsStreamState<ResponseType> implements XdsStreamState
}
clearTimeout(subscriptionEntry.resourceTimer);
subscriptionEntry.cachedResponse = resource;
if (subscriptionEntry.deletionIgnored) {
experimental.log(logVerbosity.INFO, 'Received resource with previously ignored deletion: ' + resourceName);
subscriptionEntry.deletionIgnored = false;
}
}
}
result.missing = this.handleMissingNames(allResourceNames);
Expand Down Expand Up @@ -218,10 +228,18 @@ export abstract class BaseXdsStreamState<ResponseType> implements XdsStreamState
const missingNames: string[] = [];
for (const [resourceName, subscriptionEntry] of this.subscriptions.entries()) {
if (!allResponseNames.has(resourceName) && subscriptionEntry.cachedResponse !== null) {
this.trace('Reporting resource does not exist named ' + resourceName);
missingNames.push(resourceName);
for (const watcher of subscriptionEntry.watchers) {
watcher.onResourceDoesNotExist();
if (this.ignoreResourceDeletion) {
if (!subscriptionEntry.deletionIgnored) {
experimental.log(logVerbosity.ERROR, 'Ignoring nonexistent resource ' + resourceName);
subscriptionEntry.deletionIgnored = true;
}
} else {
this.trace('Reporting resource does not exist named ' + resourceName);
missingNames.push(resourceName);
for (const watcher of subscriptionEntry.watchers) {
watcher.onResourceDoesNotExist();
}
subscriptionEntry.cachedResponse = null;
}
}
}
Expand All @@ -231,6 +249,10 @@ export abstract class BaseXdsStreamState<ResponseType> implements XdsStreamState
}
}

enableIgnoreResourceDeletion() {
this.ignoreResourceDeletion = true;
}

/**
* Apply the validation rules for this resource type to this resource
* instance.
Expand Down
2 changes: 1 addition & 1 deletion packages/grpc-js/src/experimental.ts
@@ -1,4 +1,4 @@
export { trace } from './logging';
export { trace, log } from './logging';
export {
Resolver,
ResolverListener,
Expand Down