Skip to content

Commit 6752099

Browse files
chore: remove sideeffect from ctor
1 parent 5a55c52 commit 6752099

File tree

9 files changed

+329
-288
lines changed

9 files changed

+329
-288
lines changed

src/common/exportsManager.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,17 @@ type ExportsManagerEvents = {
6363
};
6464

6565
export class ExportsManager extends EventEmitter<ExportsManagerEvents> {
66+
private wasInitialized: boolean = false;
6667
private storedExports: Record<StoredExport["exportName"], StoredExport> = {};
6768
private exportsCleanupInProgress: boolean = false;
68-
private exportsCleanupInterval: NodeJS.Timeout;
69-
private exportsDirectoryPath: string;
69+
private exportsCleanupInterval?: NodeJS.Timeout;
7070

71-
constructor(
72-
sessionId: string,
71+
private constructor(
72+
private readonly exportsDirectoryPath: string,
7373
private readonly config: ExportsManagerConfig,
7474
private readonly logger: LoggerBase
7575
) {
7676
super();
77-
this.exportsDirectoryPath = path.join(this.config.exportsPath, sessionId);
78-
this.exportsCleanupInterval = setInterval(
79-
() => void this.cleanupExpiredExports(),
80-
this.config.exportCleanupIntervalMs
81-
);
8277
}
8378

8479
public get availableExports(): AvailableExport[] {
@@ -96,6 +91,17 @@ export class ExportsManager extends EventEmitter<ExportsManagerEvents> {
9691
}));
9792
}
9893

94+
protected init(): void {
95+
if (!this.wasInitialized) {
96+
this.exportsCleanupInterval = setInterval(
97+
() => void this.cleanupExpiredExports(),
98+
this.config.exportCleanupIntervalMs
99+
);
100+
101+
this.wasInitialized = true;
102+
}
103+
}
104+
99105
public async close(): Promise<void> {
100106
try {
101107
clearInterval(this.exportsCleanupInterval);
@@ -302,6 +308,13 @@ export class ExportsManager extends EventEmitter<ExportsManagerEvents> {
302308
}
303309
}
304310
}
311+
312+
static init(sessionId: string, config: ExportsManagerConfig, logger: LoggerBase): ExportsManager {
313+
const exportsDirectoryPath = path.join(config.exportsPath, sessionId);
314+
const exportsManager = new ExportsManager(exportsDirectoryPath, config, logger);
315+
exportsManager.init();
316+
return exportsManager;
317+
}
305318
}
306319

307320
/**

src/transports/base.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export abstract class TransportRunnerBase {
4444

4545
const logger = new CompositeLogger(...loggers);
4646
const sessionId = new ObjectId().toString();
47-
const exportsManager = new ExportsManager(sessionId, userConfig, logger);
47+
const exportsManager = ExportsManager.init(sessionId, userConfig, logger);
4848
const connectionManager = new ConnectionManager();
4949

5050
const session = new Session({

tests/integration/helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export function setupIntegrationTest(getUserConfig: () => UserConfig): Integrati
5959

6060
const logger = new CompositeLogger();
6161
const sessionId = new ObjectId().toString();
62-
const exportsManager = new ExportsManager(sessionId, userConfig, logger);
62+
const exportsManager = ExportsManager.init(sessionId, userConfig, logger);
6363
const connectionManager = new ConnectionManager();
6464

6565
const session = new Session({

tests/integration/resources/exportedData.test.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1+
import path from "path";
2+
import fs from "fs/promises";
13
import { Long } from "bson";
2-
import { describe, expect, it, beforeEach } from "vitest";
4+
import { describe, expect, it, beforeEach, afterAll } from "vitest";
35
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
46
import { defaultTestConfig, resourceChangedNotification, timeout } from "../helpers.js";
57
import { describeWithMongoDB } from "../tools/mongodb/mongodbHelpers.js";
68
import { contentWithResourceURILink } from "../tools/mongodb/read/export.test.js";
9+
import { UserConfig } from "../../../src/lib.js";
10+
11+
const userConfig: UserConfig = {
12+
...defaultTestConfig,
13+
exportsPath: path.join(path.dirname(defaultTestConfig.exportsPath), `exports-${Date.now()}`),
14+
exportTimeoutMs: 200,
15+
exportCleanupIntervalMs: 300,
16+
};
717

818
describeWithMongoDB(
919
"exported-data resource",
@@ -19,6 +29,10 @@ describeWithMongoDB(
1929
]);
2030
});
2131

32+
afterAll(async () => {
33+
await fs.rm(userConfig.exportsPath, { recursive: true, force: true });
34+
});
35+
2236
it("should be able to list resource template", async () => {
2337
await integration.connectMcpClient();
2438
const response = await integration.mcpClient().listResourceTemplates();
@@ -123,11 +137,5 @@ describeWithMongoDB(
123137
});
124138
});
125139
},
126-
() => {
127-
return {
128-
...defaultTestConfig,
129-
exportTimeoutMs: 200,
130-
exportCleanupIntervalMs: 300,
131-
};
132-
}
140+
() => userConfig
133141
);

tests/integration/telemetry.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ describe("Telemetry", () => {
2020
apiBaseUrl: "",
2121
logger: new CompositeLogger(),
2222
sessionId: "1FOO",
23-
exportsManager: new ExportsManager("1FOO", config, logger),
23+
exportsManager: ExportsManager.init("1FOO", config, logger),
2424
connectionManager: new ConnectionManager(),
2525
}),
2626
config

0 commit comments

Comments
 (0)