Skip to content

Commit 720be15

Browse files
committed
Revert "reformat"
This reverts commit ae1d6d0.
1 parent 68a462e commit 720be15

File tree

1 file changed

+62
-122
lines changed

1 file changed

+62
-122
lines changed

src/tools/atlas/connect/connectCluster.ts

Lines changed: 62 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@ import { inspectCluster } from "../../../common/atlas/cluster.js";
88
import { ensureCurrentIpInAccessList } from "../../../common/atlas/accessListUtils.js";
99
import { AtlasClusterConnectionInfo } from "../../../common/connectionManager.js";
1010

11-
// Connection configuration constants
12-
const USER_EXPIRY_MS = 1000 * 60 * 60 * 12; // 12 hours
13-
const CONNECTION_RETRY_ATTEMPTS = 600; // 5 minutes (600 * 500ms = 5 minutes)
14-
const CONNECTION_RETRY_DELAY_MS = 500; // 500ms between retries
15-
const CONNECTION_CHECK_ATTEMPTS = 60; // 30 seconds (60 * 500ms = 30 seconds)
16-
const CONNECTION_CHECK_DELAY_MS = 500; // 500ms between connection state checks
11+
const EXPIRY_MS = 1000 * 60 * 60 * 12; // 12 hours
1712

1813
function sleep(ms: number): Promise<void> {
1914
return new Promise((resolve) => setTimeout(resolve, ms));
@@ -28,45 +23,6 @@ export class ConnectClusterTool extends AtlasToolBase {
2823
clusterName: z.string().describe("Atlas cluster name"),
2924
};
3025

31-
private determineReadOnlyRole(): boolean {
32-
if (this.config.readOnly) return true;
33-
34-
const disabledTools = this.config.disabledTools || [];
35-
const hasWriteAccess =
36-
!disabledTools.includes("create") && !disabledTools.includes("update") && !disabledTools.includes("delete");
37-
const hasReadAccess = !disabledTools.includes("read") && !disabledTools.includes("metadata");
38-
39-
return !hasWriteAccess && hasReadAccess;
40-
}
41-
42-
private isConnectedToOtherCluster(projectId: string, clusterName: string): boolean {
43-
return (
44-
this.session.isConnectedToMongoDB &&
45-
(!this.session.connectedAtlasCluster ||
46-
this.session.connectedAtlasCluster.projectId !== projectId ||
47-
this.session.connectedAtlasCluster.clusterName !== clusterName)
48-
);
49-
}
50-
51-
private getConnectionState(): "connected" | "connecting" | "disconnected" | "errored" {
52-
const state = this.session.connectionManager.currentConnectionState;
53-
switch (state.tag) {
54-
case "connected":
55-
return "connected";
56-
case "connecting":
57-
return "connecting";
58-
case "disconnected":
59-
return "disconnected";
60-
case "errored":
61-
return "errored";
62-
}
63-
}
64-
65-
private getErrorReason(): string | undefined {
66-
const state = this.session.connectionManager.currentConnectionState;
67-
return state.tag === "errored" ? state.errorReason : undefined;
68-
}
69-
7026
private queryConnection(
7127
projectId: string,
7228
clusterName: string
@@ -78,40 +34,52 @@ export class ConnectClusterTool extends AtlasToolBase {
7834
return "disconnected";
7935
}
8036

81-
if (this.isConnectedToOtherCluster(projectId, clusterName)) {
37+
const currentConectionState = this.session.connectionManager.currentConnectionState;
38+
if (
39+
this.session.connectedAtlasCluster.projectId !== projectId ||
40+
this.session.connectedAtlasCluster.clusterName !== clusterName
41+
) {
8242
return "connected-to-other-cluster";
8343
}
8444

85-
const connectionState = this.getConnectionState();
86-
switch (connectionState) {
45+
switch (currentConectionState.tag) {
8746
case "connecting":
8847
case "disconnected": // we might still be calling Atlas APIs and not attempted yet to connect to MongoDB, but we are still "connecting"
8948
return "connecting";
9049
case "connected":
9150
return "connected";
9251
case "errored":
93-
const errorReason = this.getErrorReason();
9452
this.session.logger.debug({
9553
id: LogId.atlasConnectFailure,
9654
context: "atlas-connect-cluster",
97-
message: `error querying cluster: ${errorReason || "unknown error"}`,
55+
message: `error querying cluster: ${currentConectionState.errorReason}`,
9856
});
9957
return "unknown";
10058
}
10159
}
10260

103-
private async createDatabaseUser(
61+
private async prepareClusterConnection(
10462
projectId: string,
105-
clusterName: string,
106-
readOnly: boolean
107-
): Promise<{
108-
username: string;
109-
password: string;
110-
expiryDate: Date;
111-
}> {
63+
clusterName: string
64+
): Promise<{ connectionString: string; atlas: AtlasClusterConnectionInfo }> {
65+
const cluster = await inspectCluster(this.session.apiClient, projectId, clusterName);
66+
67+
if (!cluster.connectionString) {
68+
throw new Error("Connection string not available");
69+
}
70+
11271
const username = `mcpUser${Math.floor(Math.random() * 100000)}`;
11372
const password = await generateSecurePassword();
114-
const expiryDate = new Date(Date.now() + USER_EXPIRY_MS);
73+
74+
const expiryDate = new Date(Date.now() + EXPIRY_MS);
75+
76+
const readOnly =
77+
this.config.readOnly ||
78+
(this.config.disabledTools?.includes("create") &&
79+
this.config.disabledTools?.includes("update") &&
80+
this.config.disabledTools?.includes("delete") &&
81+
!this.config.disabledTools?.includes("read") &&
82+
!this.config.disabledTools?.includes("metadata"));
11583

11684
const roleName = readOnly ? "readAnyDatabase" : "readWriteAnyDatabase";
11785

@@ -141,40 +109,19 @@ export class ConnectClusterTool extends AtlasToolBase {
141109
},
142110
});
143111

144-
return { username, password, expiryDate };
145-
}
146-
147-
private buildConnectionString(clusterConnectionString: string, username: string, password: string): string {
148-
const cn = new URL(clusterConnectionString);
149-
cn.username = username;
150-
cn.password = password;
151-
cn.searchParams.set("authSource", "admin");
152-
return cn.toString();
153-
}
154-
155-
private async prepareClusterConnection(
156-
projectId: string,
157-
clusterName: string
158-
): Promise<{ connectionString: string; atlas: AtlasClusterConnectionInfo }> {
159-
const cluster = await inspectCluster(this.session.apiClient, projectId, clusterName);
160-
161-
if (!cluster.connectionString) {
162-
throw new Error("Connection string not available");
163-
}
164-
165-
const readOnly = this.determineReadOnlyRole();
166-
const { username, password, expiryDate } = await this.createDatabaseUser(projectId, clusterName, readOnly);
167-
168112
const connectedAtlasCluster = {
169113
username,
170114
projectId,
171115
clusterName,
172116
expiryDate,
173117
};
174118

175-
const connectionString = this.buildConnectionString(cluster.connectionString, username, password);
119+
const cn = new URL(cluster.connectionString);
120+
cn.username = username;
121+
cn.password = password;
122+
cn.searchParams.set("authSource", "admin");
176123

177-
return { connectionString, atlas: connectedAtlasCluster };
124+
return { connectionString: cn.toString(), atlas: connectedAtlasCluster };
178125
}
179126

180127
private async connectToCluster(connectionString: string, atlas: AtlasClusterConnectionInfo): Promise<void> {
@@ -188,7 +135,7 @@ export class ConnectClusterTool extends AtlasToolBase {
188135
});
189136

190137
// try to connect for about 5 minutes
191-
for (let i = 0; i < CONNECTION_RETRY_ATTEMPTS; i++) {
138+
for (let i = 0; i < 600; i++) {
192139
try {
193140
lastError = undefined;
194141

@@ -205,7 +152,7 @@ export class ConnectClusterTool extends AtlasToolBase {
205152
message: `error connecting to cluster: ${error.message}`,
206153
});
207154

208-
await sleep(CONNECTION_RETRY_DELAY_MS); // wait for 500ms before retrying
155+
await sleep(500); // wait for 500ms before retrying
209156
}
210157

211158
if (
@@ -218,7 +165,30 @@ export class ConnectClusterTool extends AtlasToolBase {
218165
}
219166

220167
if (lastError) {
221-
await this.cleanupDatabaseUserOnFailure(atlas);
168+
if (
169+
this.session.connectedAtlasCluster?.projectId === atlas.projectId &&
170+
this.session.connectedAtlasCluster?.clusterName === atlas.clusterName &&
171+
this.session.connectedAtlasCluster?.username
172+
) {
173+
void this.session.apiClient
174+
.deleteDatabaseUser({
175+
params: {
176+
path: {
177+
groupId: this.session.connectedAtlasCluster.projectId,
178+
username: this.session.connectedAtlasCluster.username,
179+
databaseName: "admin",
180+
},
181+
},
182+
})
183+
.catch((err: unknown) => {
184+
const error = err instanceof Error ? err : new Error(String(err));
185+
this.session.logger.debug({
186+
id: LogId.atlasConnectFailure,
187+
context: "atlas-connect-cluster",
188+
message: `error deleting database user: ${error.message}`,
189+
});
190+
});
191+
}
222192
throw lastError;
223193
}
224194

@@ -230,37 +200,9 @@ export class ConnectClusterTool extends AtlasToolBase {
230200
});
231201
}
232202

233-
private async cleanupDatabaseUserOnFailure(atlas: AtlasClusterConnectionInfo): Promise<void> {
234-
const currentCluster = this.session.connectedAtlasCluster;
235-
if (
236-
currentCluster?.projectId === atlas.projectId &&
237-
currentCluster?.clusterName === atlas.clusterName &&
238-
currentCluster?.username
239-
) {
240-
try {
241-
await this.session.apiClient.deleteDatabaseUser({
242-
params: {
243-
path: {
244-
groupId: currentCluster.projectId,
245-
username: currentCluster.username,
246-
databaseName: "admin",
247-
},
248-
},
249-
});
250-
} catch (err: unknown) {
251-
const error = err instanceof Error ? err : new Error(String(err));
252-
this.session.logger.debug({
253-
id: LogId.atlasConnectFailure,
254-
context: "atlas-connect-cluster",
255-
message: `error deleting database user: ${error.message}`,
256-
});
257-
}
258-
}
259-
}
260-
261203
protected async execute({ projectId, clusterName }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
262204
await ensureCurrentIpInAccessList(this.session.apiClient, projectId);
263-
for (let i = 0; i < CONNECTION_CHECK_ATTEMPTS; i++) {
205+
for (let i = 0; i < 60; i++) {
264206
const state = this.queryConnection(projectId, clusterName);
265207
switch (state) {
266208
case "connected": {
@@ -284,21 +226,19 @@ export class ConnectClusterTool extends AtlasToolBase {
284226
const { connectionString, atlas } = await this.prepareClusterConnection(projectId, clusterName);
285227

286228
// try to connect for about 5 minutes asynchronously
287-
try {
288-
await this.connectToCluster(connectionString, atlas);
289-
} catch (err: unknown) {
229+
void this.connectToCluster(connectionString, atlas).catch((err: unknown) => {
290230
const error = err instanceof Error ? err : new Error(String(err));
291231
this.session.logger.error({
292232
id: LogId.atlasConnectFailure,
293233
context: "atlas-connect-cluster",
294234
message: `error connecting to cluster: ${error.message}`,
295235
});
296-
}
236+
});
297237
break;
298238
}
299239
}
300240

301-
await sleep(CONNECTION_CHECK_DELAY_MS);
241+
await sleep(500);
302242
}
303243

304244
return {

0 commit comments

Comments
 (0)