From ffd8b52cfae48d6226582dbe54e78d067a91c652 Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 11:41:10 +0100 Subject: [PATCH 1/6] fix: bad auth when connecting to atlas clusters --- src/logger.ts | 1 + src/tools/atlas/metadata/connectCluster.ts | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) 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/tools/atlas/metadata/connectCluster.ts b/src/tools/atlas/metadata/connectCluster.ts index 523226ba..12f66d51 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 @@ -100,7 +101,21 @@ export class ConnectClusterTool extends AtlasToolBase { cn.searchParams.set("authSource", "admin"); const connectionString = cn.toString(); - await this.session.connectToMongoDB(connectionString, this.config.connectOptions); + for (let i = 0; i < 20; i++) { + try { + await this.session.connectToMongoDB(connectionString, this.config.connectOptions); + break; + } catch (err: unknown) { + const error = err instanceof Error ? err : new Error(String(err)); + logger.debug( + LogId.atlasConnectFailure, + "atlas-connect-cluster", + `error connecting to cluster: ${error.message}` + ); + + await new Promise((resolve) => setTimeout(resolve, 500)); + } + } return { content: [ From 4df3cd65fcba2db01ae3be63831e042ca67c98b5 Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 11:44:36 +0100 Subject: [PATCH 2/6] fix: delete current user async so we do not spend too much time on disconnection --- src/session.ts | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) 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"); From 17f7d9afecbffd6195070cf768e43bb46b2bb65d Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 11:50:34 +0100 Subject: [PATCH 3/6] fix: catch last error --- src/tools/atlas/metadata/connectCluster.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/tools/atlas/metadata/connectCluster.ts b/src/tools/atlas/metadata/connectCluster.ts index 12f66d51..785f9790 100644 --- a/src/tools/atlas/metadata/connectCluster.ts +++ b/src/tools/atlas/metadata/connectCluster.ts @@ -101,12 +101,17 @@ export class ConnectClusterTool extends AtlasToolBase { cn.searchParams.set("authSource", "admin"); const connectionString = cn.toString(); + let lastError: Error | undefined = undefined; + for (let i = 0; i < 20; i++) { try { await this.session.connectToMongoDB(connectionString, this.config.connectOptions); break; } catch (err: unknown) { const error = err instanceof Error ? err : new Error(String(err)); + + lastError = error; + logger.debug( LogId.atlasConnectFailure, "atlas-connect-cluster", @@ -117,6 +122,10 @@ export class ConnectClusterTool extends AtlasToolBase { } } + if (lastError) { + throw lastError; + } + return { content: [ { From fef64f00f8788817673f5da9a6927ac7c07290f6 Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 11:52:59 +0100 Subject: [PATCH 4/6] fix: sleep --- src/tools/atlas/metadata/connectCluster.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tools/atlas/metadata/connectCluster.ts b/src/tools/atlas/metadata/connectCluster.ts index 785f9790..8fbee35f 100644 --- a/src/tools/atlas/metadata/connectCluster.ts +++ b/src/tools/atlas/metadata/connectCluster.ts @@ -16,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"; @@ -118,7 +122,7 @@ export class ConnectClusterTool extends AtlasToolBase { `error connecting to cluster: ${error.message}` ); - await new Promise((resolve) => setTimeout(resolve, 500)); + await sleep(500); // wait for 500ms before retrying } } From 8847cacf3f6ab501d5560a856e698c297b51cd88 Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 11:53:25 +0100 Subject: [PATCH 5/6] fix: last error --- src/tools/atlas/metadata/connectCluster.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/atlas/metadata/connectCluster.ts b/src/tools/atlas/metadata/connectCluster.ts index 8fbee35f..1bed7179 100644 --- a/src/tools/atlas/metadata/connectCluster.ts +++ b/src/tools/atlas/metadata/connectCluster.ts @@ -110,6 +110,7 @@ export class ConnectClusterTool extends AtlasToolBase { 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)); From d1fa4227f1b1ae03d13dad489716bbedea75f73b Mon Sep 17 00:00:00 2001 From: Filipe C Menezes Date: Wed, 30 Apr 2025 12:40:28 +0100 Subject: [PATCH 6/6] fix: error message --- src/tools/tool.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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, }; }