Skip to content

Commit 6f5431c

Browse files
committed
Add retries when downloading external editors [ci skip]
Only show in developer changelog
1 parent 11a096d commit 6f5431c

File tree

2 files changed

+100
-46
lines changed

2 files changed

+100
-46
lines changed

newIDE/app/scripts/import-zipped-editor.js

Lines changed: 56 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ var process = require('process');
99
var path = require('path');
1010
const { hashElement } = require('folder-hash');
1111
const { downloadLocalFile } = require('./lib/DownloadLocalFile');
12+
const { retryIfFailed } = require('./lib/RetryIfFailed');
1213

1314
const editor = process.argv[2];
1415
const gitRelease = process.argv[3];
@@ -38,7 +39,9 @@ const editorHasCorrectHash = () =>
3839
}
3940
);
4041

41-
editorHasCorrectHash().then(({ isHashCorrect }) => {
42+
(async () => {
43+
const { isHashCorrect } = await editorHasCorrectHash();
44+
4245
if (isHashCorrect) {
4346
//Nothing to do
4447
shell.echo(
@@ -59,65 +62,72 @@ editorHasCorrectHash().then(({ isHashCorrect }) => {
5962
' (be patient)...'
6063
);
6164

62-
downloadLocalFile(
63-
gitUrl + '/releases/download/v' + gitRelease + '/' + editor + '-editor.zip',
64-
zipFilePath
65-
).then(
66-
() => {
65+
try {
66+
await retryIfFailed(
67+
{ times: 3, backoff: { initialDelay: 400, factor: 2 } },
68+
() =>
69+
downloadLocalFile(
70+
gitUrl +
71+
'/releases/download/v' +
72+
gitRelease +
73+
'/' +
74+
editor +
75+
'-editor.zip',
76+
zipFilePath
77+
)
78+
);
79+
shell.echo(
80+
'📂 Extracting ' +
81+
editor +
82+
'-editor.zip to public/external/' +
83+
editor +
84+
' folder'
85+
);
86+
87+
try {
88+
const zip = new AdmZip(zipFilePath);
89+
zip.extractAllTo(
90+
path.join('../public/external/', editor),
91+
/*overwrite=*/ true
92+
);
93+
6794
shell.echo(
68-
'📂 Extracting ' +
95+
'✅ Extracted ' +
6996
editor +
7097
'-editor.zip to public/external/' +
7198
editor +
7299
' folder'
73100
);
101+
shell.rm(zipFilePath);
102+
const { isHashCorrect, actualFolderHash } = await editorHasCorrectHash();
74103

75-
try {
76-
const zip = new AdmZip(zipFilePath);
77-
zip.extractAllTo(
78-
path.join('../public/external/', editor),
79-
/*overwrite=*/ true
80-
);
81-
104+
if (!isHashCorrect) {
82105
shell.echo(
83-
'✅ Extracted ' +
106+
"❌ Can't verify that " +
84107
editor +
85-
'-editor.zip to public/external/' +
86-
editor +
87-
' folder'
108+
'-editor hash is correct. Be careful about potential tampering of the third party editor! 💣'
88109
);
89-
shell.rm(zipFilePath);
90-
editorHasCorrectHash().then(({ isHashCorrect, actualFolderHash }) => {
91-
if (!isHashCorrect) {
92-
shell.echo(
93-
"❌ Can't verify that " +
94-
editor +
95-
'-editor hash is correct. Be careful about potential tampering of the third party editor! 💣'
96-
);
97-
shell.echo(
98-
`ℹ️ Expected folder hash was "${expectedFolderHash}" while actual folder hash that is computed is "${actualFolderHash}".`
99-
);
100-
}
101-
});
102-
} catch (e) {
103110
shell.echo(
104-
'❌ Error while extracting ' +
105-
editor +
106-
'-editor.zip to public/external/' +
107-
editor +
108-
' folder:',
109-
e.message
111+
`ℹ️ Expected folder hash was "${expectedFolderHash}" while actual folder hash that is computed is "${actualFolderHash}".`
110112
);
111113
}
112-
},
113-
e => {
114+
} catch (e) {
114115
shell.echo(
115-
`❌ Can't download ` +
116+
'❌ Error while extracting ' +
117+
editor +
118+
'-editor.zip to public/external/' +
116119
editor +
117-
`-editor.zip (${e}), please check your internet connection`
120+
' folder:',
121+
e.message
118122
);
119-
shell.exit(1);
120-
return;
121123
}
122-
);
123-
});
124+
} catch (e) {
125+
shell.echo(
126+
`❌ Can't download ` +
127+
editor +
128+
`-editor.zip (${e}), please check your internet connection`
129+
);
130+
shell.exit(1);
131+
return;
132+
}
133+
})();
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// @ts-check
2+
3+
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
4+
5+
/**
6+
* @template T
7+
* @param {{
8+
* times: number,
9+
* backoff?: {
10+
* initialDelay: number, // in milliseconds
11+
* factor?: number // optional multiplier (default is 2)
12+
* }
13+
* }} configuration
14+
* @param {() => Promise<T>} functionCalled
15+
* @returns {Promise<T>}
16+
*/
17+
const retryIfFailed = async ({ times, backoff }, functionCalled) => {
18+
let tries = 0;
19+
let latestError = null;
20+
const useBackoff = !!backoff;
21+
let delayTime = (backoff && backoff.initialDelay) || 0;
22+
const factor = (backoff && backoff.factor) || 2;
23+
24+
while (tries < times) {
25+
tries++;
26+
latestError = null;
27+
try {
28+
const latestReturnValue = await functionCalled();
29+
return latestReturnValue;
30+
} catch (error) {
31+
latestError = error;
32+
if (tries < times && useBackoff) {
33+
await delay(delayTime);
34+
delayTime *= factor;
35+
}
36+
}
37+
}
38+
39+
throw latestError;
40+
};
41+
42+
module.exports = {
43+
retryIfFailed,
44+
};

0 commit comments

Comments
 (0)