Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vscode.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/vs
diff options
context:
space:
mode:
authorAlexandru Dima <alexdima@microsoft.com>2022-07-27 18:10:06 +0300
committerGitHub <noreply@github.com>2022-07-27 18:10:06 +0300
commite572968d23fa5c80d407bac507143a6f60e2c0f8 (patch)
tree020bb1a8661f6cc1ca35c3bc1b61d1644945ada0 /src/vs
parentd391f2c1ffcd270bce8c85d810e4b8a0f3822fa3 (diff)
Retry up to 5 times the initial authority resolving and also retry up to 5 times the initial connection (#156444)
Fixes #127565: Retry up to 5 times the initial authority resolving and retry up to 5 times the initial connection
Diffstat (limited to 'src/vs')
-rw-r--r--src/vs/platform/remote/common/remoteAgentConnection.ts60
-rw-r--r--src/vs/workbench/services/extensions/electron-sandbox/electronExtensionService.ts33
2 files changed, 66 insertions, 27 deletions
diff --git a/src/vs/platform/remote/common/remoteAgentConnection.ts b/src/vs/platform/remote/common/remoteAgentConnection.ts
index 2335efbde29..fde30c2d8a6 100644
--- a/src/vs/platform/remote/common/remoteAgentConnection.ts
+++ b/src/vs/platform/remote/common/remoteAgentConnection.ts
@@ -417,30 +417,48 @@ export interface IAddressProvider {
}
export async function connectRemoteAgentManagement(options: IConnectionOptions, remoteAuthority: string, clientId: string): Promise<ManagementPersistentConnection> {
- try {
- const reconnectionToken = generateUuid();
- const simpleOptions = await resolveConnectionOptions(options, reconnectionToken, null);
- const { protocol } = await doConnectRemoteAgentManagement(simpleOptions, CancellationToken.None);
- return new ManagementPersistentConnection(options, remoteAuthority, clientId, reconnectionToken, protocol);
- } catch (err) {
- options.logService.error(`[remote-connection] An error occurred in the very first connect attempt, it will be treated as a permanent error! Error:`);
- options.logService.error(err);
- PersistentConnection.triggerPermanentFailure(0, 0, RemoteAuthorityResolverError.isHandled(err));
- throw err;
- }
+ return createInitialConnection(
+ options,
+ async (simpleOptions) => {
+ const { protocol } = await doConnectRemoteAgentManagement(simpleOptions, CancellationToken.None);
+ return new ManagementPersistentConnection(options, remoteAuthority, clientId, simpleOptions.reconnectionToken, protocol);
+ }
+ );
}
export async function connectRemoteAgentExtensionHost(options: IConnectionOptions, startArguments: IRemoteExtensionHostStartParams): Promise<ExtensionHostPersistentConnection> {
- try {
- const reconnectionToken = generateUuid();
- const simpleOptions = await resolveConnectionOptions(options, reconnectionToken, null);
- const { protocol, debugPort } = await doConnectRemoteAgentExtensionHost(simpleOptions, startArguments, CancellationToken.None);
- return new ExtensionHostPersistentConnection(options, startArguments, reconnectionToken, protocol, debugPort);
- } catch (err) {
- options.logService.error(`[remote-connection] An error occurred in the very first connect attempt, it will be treated as a permanent error! Error:`);
- options.logService.error(err);
- PersistentConnection.triggerPermanentFailure(0, 0, RemoteAuthorityResolverError.isHandled(err));
- throw err;
+ return createInitialConnection(
+ options,
+ async (simpleOptions) => {
+ const { protocol, debugPort } = await doConnectRemoteAgentExtensionHost(simpleOptions, startArguments, CancellationToken.None);
+ return new ExtensionHostPersistentConnection(options, startArguments, simpleOptions.reconnectionToken, protocol, debugPort);
+ }
+ );
+}
+
+/**
+ * Will attempt to connect 5 times. If it fails 5 consecutive times, it will give up.
+ */
+async function createInitialConnection<T extends PersistentConnection>(options: IConnectionOptions, connectionFactory: (simpleOptions: ISimpleConnectionOptions) => Promise<T>): Promise<T> {
+ const MAX_ATTEMPTS = 5;
+
+ for (let attempt = 1; ; attempt++) {
+ try {
+ const reconnectionToken = generateUuid();
+ const simpleOptions = await resolveConnectionOptions(options, reconnectionToken, null);
+ const result = await connectionFactory(simpleOptions);
+ return result;
+ } catch (err) {
+ if (attempt < MAX_ATTEMPTS) {
+ options.logService.error(`[remote-connection][attempt ${attempt}] An error occurred in initial connection! Will retry... Error:`);
+ options.logService.error(err);
+ } else {
+ options.logService.error(`[remote-connection][attempt ${attempt}] An error occurred in initial connection! It will be treated as a permanent error. Error:`);
+ options.logService.error(err);
+ PersistentConnection.triggerPermanentFailure(0, 0, RemoteAuthorityResolverError.isHandled(err));
+ throw err;
+ }
+ }
}
}
diff --git a/src/vs/workbench/services/extensions/electron-sandbox/electronExtensionService.ts b/src/vs/workbench/services/extensions/electron-sandbox/electronExtensionService.ts
index 34cb13522aa..ee051e3d1f1 100644
--- a/src/vs/workbench/services/extensions/electron-sandbox/electronExtensionService.ts
+++ b/src/vs/workbench/services/extensions/electron-sandbox/electronExtensionService.ts
@@ -413,6 +413,32 @@ export abstract class ElectronExtensionService extends AbstractExtensionService
throw new Error(`Cannot get canonical URI because no extension is installed to resolve ${getRemoteAuthorityPrefix(remoteAuthority)}`);
}
+ private async _resolveAuthorityInitial(remoteAuthority: string): Promise<ResolverResult> {
+ const MAX_ATTEMPTS = 5;
+
+ for (let attempt = 1; ; attempt++) {
+ const sw = StopWatch.create(false);
+ this._logService.info(`[attempt ${attempt}] Invoking resolveAuthority(${getRemoteAuthorityPrefix(remoteAuthority)})`);
+ try {
+ const resolverResult = await this._resolveAuthority(remoteAuthority);
+ this._logService.info(`[attempt ${attempt}] resolveAuthority(${getRemoteAuthorityPrefix(remoteAuthority)}) returned '${resolverResult.authority.host}:${resolverResult.authority.port}' after ${sw.elapsed()} ms`);
+ return resolverResult;
+ } catch (err) {
+ this._logService.error(`[attempt ${attempt}] resolveAuthority(${getRemoteAuthorityPrefix(remoteAuthority)}) returned an error after ${sw.elapsed()} ms`, err);
+
+ if (RemoteAuthorityResolverError.isNoResolverFound(err)) {
+ // There is no point in retrying if there is no resolver found
+ throw err;
+ }
+
+ if (attempt >= MAX_ATTEMPTS) {
+ // Too many failed attempts, give up
+ throw err;
+ }
+ }
+ }
+ }
+
private async _resolveAuthorityAgain(): Promise<void> {
const remoteAuthority = this._environmentService.remoteAuthority;
if (!remoteAuthority) {
@@ -473,14 +499,9 @@ export abstract class ElectronExtensionService extends AbstractExtensionService
}
let resolverResult: ResolverResult;
-
- const sw = StopWatch.create(false);
- this._logService.info(`Invoking resolveAuthority(${getRemoteAuthorityPrefix(remoteAuthority)})`);
try {
- resolverResult = await this._resolveAuthority(remoteAuthority);
- this._logService.info(`resolveAuthority(${getRemoteAuthorityPrefix(remoteAuthority)}) returned '${resolverResult.authority.host}:${resolverResult.authority.port}' after ${sw.elapsed()} ms`);
+ resolverResult = await this._resolveAuthorityInitial(remoteAuthority);
} catch (err) {
- this._logService.error(`resolveAuthority(${getRemoteAuthorityPrefix(remoteAuthority)}) returned an error after ${sw.elapsed()} ms`, err);
if (RemoteAuthorityResolverError.isNoResolverFound(err)) {
err.isHandled = await this._handleNoResolverFound(remoteAuthority);
} else {