Skip to content

Commit 2bc3c60

Browse files
authored
Feature/556/better timeout error messages (#557)
* (#556) Store intermediate results and errors to provide additional context on timeout * (#556) Update testcases
1 parent 67a413a commit 2bc3c60

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

lib/util/timeout.function.spec.ts

+16-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ describe("timeout", () => {
1616
try {
1717
await timeout(updateInterval, maxDuration, action);
1818
} catch (e) {
19-
expect(e).toBe(`Action timed out after ${maxDuration} ms`);
19+
expect(e).toBe(
20+
`Action timed out after ${maxDuration} ms. Last rejection reason was: false.`,
21+
);
2022
}
2123
const end = Date.now();
2224

@@ -37,7 +39,9 @@ describe("timeout", () => {
3739
try {
3840
await timeout(updateInterval, maxDuration, action);
3941
} catch (e) {
40-
expect(e).toEqual(`Action timed out after ${maxDuration} ms`);
42+
expect(e).toEqual(
43+
`Action timed out after ${maxDuration} ms. Didn't receive a result within timeout.`,
44+
);
4145
}
4246
const end = Date.now();
4347

@@ -90,7 +94,7 @@ describe("timeout", () => {
9094
const action = jest.fn(() => {
9195
const interval = Date.now() - start;
9296
return new Promise<boolean>((resolve, reject) =>
93-
interval > delay ? resolve(true) : reject()
97+
interval > delay ? resolve(true) : reject(),
9498
);
9599
});
96100

@@ -114,7 +118,9 @@ describe("timeout", () => {
114118
try {
115119
await timeout(updateInterval, maxDuration, action);
116120
} catch (e) {
117-
expect(e).toEqual(`Action timed out after ${maxDuration} ms`);
121+
expect(e).toEqual(
122+
`Action timed out after ${maxDuration} ms. Didn't receive a result within timeout.`,
123+
);
118124
}
119125
const end = Date.now();
120126

@@ -137,7 +143,9 @@ describe("timeout", () => {
137143
const SUT = () => timeout(updateInterval, maxDuration, action);
138144

139145
// THEN
140-
await expect(SUT).rejects.toBe(`Action timed out after ${maxDuration} ms`);
146+
await expect(SUT).rejects.toBe(
147+
`Action timed out after ${maxDuration} ms. Didn't receive a result within timeout.`,
148+
);
141149
expect(action).toBeCalledTimes(1);
142150
});
143151

@@ -157,7 +165,9 @@ describe("timeout", () => {
157165
const SUT = () => timeout(updateInterval, maxDuration, action);
158166

159167
// THEN
160-
await expect(SUT).rejects.toBe(`Action timed out after ${maxDuration} ms`);
168+
await expect(SUT).rejects.toBe(
169+
`Action timed out after ${maxDuration} ms. Didn't receive a result within timeout.`,
170+
);
161171
expect(action).toBeCalledTimes(1);
162172
await sleep(500);
163173
expect(action).toBeCalledTimes(1);

lib/util/timeout.function.ts

+19-3
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ export function timeout<R>(
88
updateIntervalMs: number,
99
maxDurationMs: number,
1010
action: (...params: any) => Promise<R>,
11-
config?: TimoutConfig
11+
config?: TimoutConfig,
1212
): Promise<R> {
1313
return new Promise<R>((resolve, reject) => {
1414
let interval: NodeJS.Timeout;
1515
let timerCleaned = false;
16+
let lastResult: R | null;
17+
let lastRejectionReason: any | null;
1618

1719
if (config?.signal) {
1820
config.signal.onabort = () => {
@@ -29,12 +31,16 @@ export function timeout<R>(
2931
if (!result && !timerCleaned) {
3032
interval = setTimeout(executeInterval, updateIntervalMs);
3133
} else {
34+
lastResult = result;
35+
lastRejectionReason = null;
3236
cleanupTimer();
3337
resolve(result);
3438
}
3539
}
3640

37-
function handleRejection() {
41+
function handleRejection(reason: any) {
42+
lastRejectionReason = reason;
43+
lastResult = null;
3844
if (!timerCleaned) {
3945
interval = setTimeout(executeInterval, updateIntervalMs);
4046
}
@@ -52,7 +58,17 @@ export function timeout<R>(
5258

5359
const maxTimeout = setTimeout(() => {
5460
cleanupTimer();
55-
reject(`Action timed out after ${maxDurationMs} ms`);
61+
let additionalInformation: string | undefined;
62+
if (lastResult == null && lastRejectionReason != null) {
63+
additionalInformation = `Last rejection reason was: ${lastRejectionReason}.`;
64+
} else if (lastResult == null && lastRejectionReason == null) {
65+
additionalInformation = `Didn't receive a result within timeout.`;
66+
}
67+
reject(
68+
`Action timed out after ${maxDurationMs} ms.${
69+
additionalInformation ? ` ${additionalInformation}` : ""
70+
}`,
71+
);
5672
}, maxDurationMs);
5773

5874
executeInterval();

0 commit comments

Comments
 (0)