Skip to content

Commit cab4019

Browse files
committed
Retry binary install downloads
1 parent 33a6309 commit cab4019

3 files changed

Lines changed: 49 additions & 23 deletions

File tree

‎package-lock.json‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@node-3d/addon-tools",
3-
"version": "10.0.4",
3+
"version": "10.0.5",
44
"description": "Helpers for Node.js addons and dependency packages",
55
"keywords": [
66
"addon",

‎ts/utils/install.ts‎

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,48 @@
1-
import { exec as execCallback } from 'node:child_process';
1+
import { execFile as execFileCallback } from 'node:child_process';
22
import fs from 'node:fs/promises';
3+
import { setTimeout } from 'node:timers/promises';
34
import { promisify } from 'node:util';
45
import { getBin, getPlatform } from '../include.ts';
56
import { exists, rm, rmdir } from './files.ts';
67
import { getLogger } from './logger.ts';
78

8-
const exec = promisify(execCallback);
9+
const execFile = promisify(execFileCallback);
910
const logger = getLogger('addon-tools');
11+
const ONE_SECOND_MS = 1000;
12+
const RETRY_DELAYS_MS = [ONE_SECOND_MS * 2, ONE_SECOND_MS * 5] as const;
1013

11-
const download = async (url: string) => {
12-
const { stderr } = await exec(
13-
['curl -fsSL -o', `${getBin()}/${getPlatform()}.gz`, url].join(' '),
14-
);
14+
const download = async (url: string, gzPath: string) => {
15+
const { stderr } = await execFile('curl', ['-fsSL', '-o', gzPath, url]);
1516
if (stderr) {
1617
logger.warn(stderr);
1718
}
1819
};
1920

2021
const unpack = async (gzPath: string, binPath: string) => {
21-
const { stderr } = await exec(`tar -xzf ${gzPath} --directory ${binPath}`);
22+
const { stderr } = await execFile('tar', ['-xzf', gzPath, '--directory', binPath]);
2223
if (stderr) {
2324
logger.warn(stderr);
2425
}
2526
};
2627

28+
const waitBeforeRetry = async (attempt: number): Promise<void> => {
29+
const delayMs = RETRY_DELAYS_MS[attempt - 1] ?? RETRY_DELAYS_MS.at(-1);
30+
if (delayMs) {
31+
await setTimeout(delayMs);
32+
}
33+
};
34+
35+
const tryInstall = async (urlPath: string, gzPath: string, binPath: string): Promise<boolean> => {
36+
await download(urlPath, gzPath);
37+
38+
if (!(await exists(gzPath))) {
39+
throw new Error(`Could not download "${urlPath}" to "${gzPath}"`);
40+
}
41+
42+
await unpack(gzPath, binPath);
43+
return true;
44+
};
45+
2746
export const install = async (folderUrl: string): Promise<boolean> => {
2847
const binPath = getBin();
2948
const urlPath = `${folderUrl}/${getPlatform()}.gz`;
@@ -32,20 +51,27 @@ export const install = async (folderUrl: string): Promise<boolean> => {
3251
await rmdir(binPath);
3352
await fs.mkdir(binPath, { recursive: true });
3453

35-
try {
36-
await download(urlPath);
54+
// oxlint-disable no-await-in-loop
55+
for (let attempt = 1; attempt <= RETRY_DELAYS_MS.length + 1; attempt++) {
56+
try {
57+
const isInstalled = await tryInstall(urlPath, gzPath, binPath);
58+
await rm(gzPath).catch((rmError: unknown) => logger.warn(rmError));
59+
return isInstalled;
60+
} catch (error) {
61+
logger.warn(error);
62+
await rm(gzPath).catch((rmError: unknown) => logger.warn(rmError));
3763

38-
if (!(await exists(gzPath))) {
39-
logger.warn(`Could not download "${urlPath}" to "${gzPath}"`);
40-
return false;
41-
}
64+
if (attempt > RETRY_DELAYS_MS.length) {
65+
return false;
66+
}
4267

43-
await unpack(gzPath, binPath);
44-
} catch (error) {
45-
logger.warn(error);
46-
return false;
47-
} finally {
48-
await rm(gzPath).catch((error: unknown) => logger.warn(error));
68+
logger.warn(
69+
`Retrying install from "${urlPath}" (${attempt}/${RETRY_DELAYS_MS.length})`,
70+
);
71+
await waitBeforeRetry(attempt);
72+
}
4973
}
50-
return true;
74+
// oxlint-enable no-await-in-loop
75+
76+
return false;
5177
};

0 commit comments

Comments
 (0)