test(e2e): a page load the machine had no buffer for is tried again
net::ERR_NO_BUFFER_SPACE stopped a release at its first page with nothing else running, and the unchanged rerun passed. Every page load of the suite now goes through one helper, held by a test.
This commit is contained in:
@@ -11,6 +11,19 @@ const METHODS = new Set(["get", "post", "put", "patch", "delete", "head", "fetch
|
||||
const NO_CONNECTION = /\bconnect ETIMEDOUT\b/;
|
||||
const WAITS_MS = [500, 1000, 2000, 4000, 8000];
|
||||
|
||||
/** `attempt` again after each wait while it fails with `transient`; any other failure goes on. */
|
||||
async function tryAgain<R>(attempt: () => Promise<R>, transient: RegExp): Promise<R> {
|
||||
for (let i = 0; ; i++) {
|
||||
try {
|
||||
return await attempt();
|
||||
} catch (e) {
|
||||
const wait = WAITS_MS[i];
|
||||
if (wait === undefined || !transient.test(String((e as Error)?.message))) throw e;
|
||||
await new Promise((r) => setTimeout(r, wait));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** `ctx` with its request methods trying a connect that timed out again (see above). */
|
||||
export function retryConnect<T extends object>(ctx: T): T {
|
||||
return new Proxy(ctx, {
|
||||
@@ -18,17 +31,19 @@ export function retryConnect<T extends object>(ctx: T): T {
|
||||
const v: unknown = Reflect.get(target, key, target);
|
||||
if (typeof v !== "function") return v;
|
||||
if (typeof key !== "string" || !METHODS.has(key)) return v.bind(target);
|
||||
return async (...args: unknown[]) => {
|
||||
for (let i = 0; ; i++) {
|
||||
try {
|
||||
return await v.apply(target, args);
|
||||
} catch (e) {
|
||||
const wait = WAITS_MS[i];
|
||||
if (wait === undefined || !NO_CONNECTION.test(String((e as Error)?.message))) throw e;
|
||||
await new Promise((r) => setTimeout(r, wait));
|
||||
}
|
||||
}
|
||||
};
|
||||
return (...args: unknown[]) =>
|
||||
tryAgain(() => Promise.resolve(v.apply(target, args)), NO_CONNECTION);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// A page load has a failure of its own on the same machine: `net::ERR_NO_BUFFER_SPACE`, the socket
|
||||
// call refused for the moment. It stopped a release's e2e at its first page (0.116.3, with nothing
|
||||
// else running; 0.107.3 aborted on it too), and the unchanged rerun passed. A browser does not try
|
||||
// a main document again by itself, and the request never left, so this does. The suite's every page
|
||||
// load goes through here (`e2eRetryConnect.test.ts`).
|
||||
const NO_BUFFER = /\bERR_NO_BUFFER_SPACE\b/;
|
||||
|
||||
export function gotoRetrying<R>(page: { goto(url: string): Promise<R> }, url: string): Promise<R> {
|
||||
return tryAgain(() => page.goto(url), NO_BUFFER);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user