diff --git a/src/logger.ts b/src/logger.ts index 3a098bf1..bdd439e1 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -12,6 +12,7 @@ export const LogId = { atlasCheckCredentials: mongoLogId(1_001_001), atlasDeleteDatabaseUserFailure: mongoLogId(1_001_002), + atlasConnectFailure: mongoLogId(1_001_003), telemetryDisabled: mongoLogId(1_002_001), telemetryEmitFailure: mongoLogId(1_002_002), diff --git a/src/session.ts b/src/session.ts index 57053688..6f219c41 100644 --- a/src/session.ts +++ b/src/session.ts @@ -69,8 +69,8 @@ export class Session extends EventEmitter<{ this.emit("disconnect"); return; } - try { - await this.apiClient.deleteDatabaseUser({ + void this.apiClient + .deleteDatabaseUser({ params: { path: { groupId: this.connectedAtlasCluster.projectId, @@ -78,16 +78,15 @@ export class Session extends EventEmitter<{ databaseName: "admin", }, }, + }) + .catch((err: unknown) => { + const error = err instanceof Error ? err : new Error(String(err)); + logger.error( + LogId.atlasDeleteDatabaseUserFailure, + "atlas-connect-cluster", + `Error deleting previous database user: ${error.message}` + ); }); - } catch (err: unknown) { - const error = err instanceof Error ? err : new Error(String(err)); - - logger.error( - LogId.atlasDeleteDatabaseUserFailure, - "atlas-connect-cluster", - `Error deleting previous database user: ${error.message}` - ); - } this.connectedAtlasCluster = undefined; this.emit("disconnect"); diff --git a/src/tools/atlas/metadata/connectCluster.ts b/src/tools/atlas/metadata/connectCluster.ts index 523226ba..1bed7179 100644 --- a/src/tools/atlas/metadata/connectCluster.ts +++ b/src/tools/atlas/metadata/connectCluster.ts @@ -4,6 +4,7 @@ import { AtlasToolBase } from "../atlasTool.js"; import { ToolArgs, OperationType } from "../../tool.js"; import { randomBytes } from "crypto"; import { promisify } from "util"; +import logger, { LogId } from "../../../logger.js"; const EXPIRY_MS = 1000 * 60 * 60 * 12; // 12 hours @@ -15,6 +16,10 @@ async function generateSecurePassword(): Promise { return pass; } +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + export class ConnectClusterTool extends AtlasToolBase { protected name = "atlas-connect-cluster"; protected description = "Connect to MongoDB Atlas cluster"; @@ -100,7 +105,31 @@ export class ConnectClusterTool extends AtlasToolBase { cn.searchParams.set("authSource", "admin"); const connectionString = cn.toString(); - await this.session.connectToMongoDB(connectionString, this.config.connectOptions); + let lastError: Error | undefined = undefined; + + for (let i = 0; i < 20; i++) { + try { + await this.session.connectToMongoDB(connectionString, this.config.connectOptions); + lastError = undefined; + break; + } catch (err: unknown) { + const error = err instanceof Error ? err : new Error(String(err)); + + lastError = error; + + logger.debug( + LogId.atlasConnectFailure, + "atlas-connect-cluster", + `error connecting to cluster: ${error.message}` + ); + + await sleep(500); // wait for 500ms before retrying + } + } + + if (lastError) { + throw lastError; + } return { content: [ diff --git a/src/tools/tool.ts b/src/tools/tool.ts index b6b00eda..5e4fc1a3 100644 --- a/src/tools/tool.ts +++ b/src/tools/tool.ts @@ -126,9 +126,9 @@ export abstract class ToolBase { { type: "text", text: `Error running ${this.name}: ${error instanceof Error ? error.message : String(error)}`, - isError: true, }, ], + isError: true, }; }