Skip to content

Commit 3c111b0

Browse files
committed
fix tests, refactor deviceId
1 parent 24097c3 commit 3c111b0

File tree

3 files changed

+56
-62
lines changed

3 files changed

+56
-62
lines changed

src/helpers/deviceId.ts

Lines changed: 21 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,89 +5,58 @@ import { LogId, LoggerBase } from "../common/logger.js";
55
export const DEVICE_ID_TIMEOUT = 3000;
66

77
export class DeviceId {
8-
private deviceId: string | undefined = undefined;
9-
private deviceIdPromise: Promise<string> | undefined = undefined;
10-
private abortController: AbortController | undefined = undefined;
8+
private static readonly UnknownDeviceId = Promise.resolve("unknown");
9+
10+
private deviceIdPromise: Promise<string>;
11+
private abortController: AbortController;
1112
private logger: LoggerBase;
1213
private readonly getMachineId: () => Promise<string>;
1314
private timeout: number;
14-
private static instance: DeviceId | undefined = undefined;
1515

1616
private constructor(logger: LoggerBase, timeout: number = DEVICE_ID_TIMEOUT) {
1717
this.logger = logger;
1818
this.timeout = timeout;
1919
this.getMachineId = (): Promise<string> => nodeMachineId.machineId(true);
20+
this.abortController = new AbortController();
21+
22+
this.deviceIdPromise = DeviceId.UnknownDeviceId;
2023
}
2124

22-
public static create(logger: LoggerBase, timeout?: number): DeviceId {
23-
if (this.instance) {
24-
throw new Error("DeviceId instance already exists, use get() to retrieve the device ID");
25-
}
25+
private initialize(): void {
26+
this.deviceIdPromise = getDeviceId({
27+
getMachineId: this.getMachineId,
28+
onError: (reason, error) => {
29+
this.handleDeviceIdError(reason, String(error));
30+
},
31+
timeout: this.timeout,
32+
abortSignal: this.abortController.signal,
33+
});
34+
}
2635

36+
public static create(logger: LoggerBase, timeout?: number): DeviceId {
2737
const instance = new DeviceId(logger, timeout ?? DEVICE_ID_TIMEOUT);
28-
instance.setup();
29-
30-
this.instance = instance;
38+
instance.initialize();
3139

3240
return instance;
3341
}
3442

35-
private setup(): void {
36-
this.deviceIdPromise = this.calculateDeviceId();
37-
}
38-
3943
/**
4044
* Closes the device ID calculation promise and abort controller.
4145
*/
4246
public close(): void {
43-
if (this.abortController) {
44-
this.abortController.abort();
45-
this.abortController = undefined;
46-
}
47-
48-
this.deviceId = undefined;
49-
this.deviceIdPromise = undefined;
50-
DeviceId.instance = undefined;
47+
this.abortController.abort();
5148
}
5249

5350
/**
5451
* Gets the device ID, waiting for the calculation to complete if necessary.
5552
* @returns Promise that resolves to the device ID string
5653
*/
5754
public get(): Promise<string> {
58-
if (this.deviceId) {
59-
return Promise.resolve(this.deviceId);
60-
}
61-
62-
if (this.deviceIdPromise) {
63-
return this.deviceIdPromise;
64-
}
65-
66-
return this.calculateDeviceId();
67-
}
68-
69-
/**
70-
* Internal method that performs the actual device ID calculation.
71-
*/
72-
private async calculateDeviceId(): Promise<string> {
73-
if (!this.abortController) {
74-
this.abortController = new AbortController();
75-
}
76-
77-
this.deviceIdPromise = getDeviceId({
78-
getMachineId: this.getMachineId,
79-
onError: (reason, error) => {
80-
this.handleDeviceIdError(reason, String(error));
81-
},
82-
timeout: this.timeout,
83-
abortSignal: this.abortController.signal,
84-
});
85-
8655
return this.deviceIdPromise;
8756
}
8857

8958
private handleDeviceIdError(reason: string, error: string): void {
90-
this.deviceIdPromise = Promise.resolve("unknown");
59+
this.deviceIdPromise = DeviceId.UnknownDeviceId;
9160

9261
switch (reason) {
9362
case "resolutionError":

tests/integration/transports/streamableHttp.test.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,6 @@ describe("StreamableHttpRunner", () => {
1717
config.httpPort = 0; // Use a random port for testing
1818
});
1919

20-
afterAll(async () => {
21-
await runner.close();
22-
config.telemetry = oldTelemetry;
23-
config.loggers = oldLoggers;
24-
});
25-
2620
const headerTestCases: { headers: Record<string, string>; description: string }[] = [
2721
{ headers: {}, description: "without headers" },
2822
{ headers: { "x-custom-header": "test-value" }, description: "with headers" },
@@ -36,6 +30,13 @@ describe("StreamableHttpRunner", () => {
3630
await runner.start();
3731
});
3832

33+
afterAll(async () => {
34+
await runner.close();
35+
config.telemetry = oldTelemetry;
36+
config.loggers = oldLoggers;
37+
config.httpHeaders = {};
38+
});
39+
3940
const clientHeaderTestCases = [
4041
{
4142
headers: {},
@@ -100,4 +101,23 @@ describe("StreamableHttpRunner", () => {
100101
}
101102
});
102103
}
104+
105+
it("can create multiple runners", async () => {
106+
const runners: StreamableHttpRunner[] = [];
107+
try {
108+
for (let i = 0; i < 3; i++) {
109+
config.httpPort = 0; // Use a random port for each runner
110+
const runner = new StreamableHttpRunner(config);
111+
await runner.start();
112+
runners.push(runner);
113+
}
114+
115+
const addresses = new Set<string>(runners.map((r) => r.address));
116+
expect(addresses.size).toBe(runners.length);
117+
} finally {
118+
for (const runner of runners) {
119+
await runner.close();
120+
}
121+
}
122+
});
103123
});

tests/unit/helpers/deviceId.test.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,16 @@ describe("deviceId", () => {
2222
deviceId.close();
2323
});
2424

25-
it("should fail to create separate instances", () => {
25+
it("should return different instance from create", async () => {
2626
deviceId = DeviceId.create(testLogger);
27-
28-
// try to create a new device id and see it raises an error
29-
expect(() => DeviceId.create(testLogger)).toThrow("DeviceId instance already exists");
27+
let second: DeviceId | undefined;
28+
try {
29+
second = DeviceId.create(testLogger);
30+
expect(second === deviceId).toBe(false);
31+
expect(await second.get()).toBe(await deviceId.get());
32+
} finally {
33+
second?.close();
34+
}
3035
});
3136

3237
it("should successfully retrieve device ID", async () => {

0 commit comments

Comments
 (0)