Skip to content

Commit 0aa9fce

Browse files
authored
2.7.4 (#73)
* improvement: add retry mechanism with exponential backoff to improve reliability for Google Cloud Storage API PUT errors * 2.7.4-alpha.1 * 2.7.4
1 parent d53afef commit 0aa9fce

3 files changed

Lines changed: 39 additions & 11 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": "@appcircle/cli",
3-
"version": "2.7.3",
3+
"version": "2.7.4",
44
"description": "CLI tool for running Appcircle services from the command line",
55
"main": "bin/appcircle.js",
66
"bin": {

src/services/index.ts

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,40 @@ export async function uploadArtifact(options: OptionsType<{ message: string; app
317317
return uploadResponse.data;
318318
}
319319

320+
async function putUploadWithRetry(url: string, file: fs.ReadStream, headers: any, maxRetries = 5) {
321+
let attempt = 0;
322+
let delay = 1000;
323+
324+
while (true) {
325+
try {
326+
return await axios.put(url, file, {
327+
maxContentLength: Infinity,
328+
maxBodyLength: Infinity,
329+
headers,
330+
transformRequest: [(d) => d],
331+
responseType: 'arraybuffer',
332+
});
333+
} catch (error: any) {
334+
const status = error?.response?.status;
335+
const retryable =
336+
status === 503 ||
337+
error?.code === 'ECONNRESET' ||
338+
error?.message?.includes('socket hang up');
339+
340+
if (!retryable || attempt >= maxRetries) {
341+
throw error;
342+
}
343+
attempt++;
344+
const jitter = Math.floor(Math.random() * 300);
345+
346+
await new Promise((resolve) => setTimeout(resolve, delay + jitter)); // SLEEP
347+
348+
delay *= 2;
349+
}
350+
}
351+
352+
}
353+
320354
export async function uploadArtifactWithSignedUrl(
321355
options: OptionsType<{ app: string; uploadInfo: FileUploadInformation }>
322356
) {
@@ -338,15 +372,9 @@ export async function uploadArtifactWithSignedUrl(
338372

339373
if (!configuration || !configuration.httpMethod || configuration.httpMethod === 'PUT') {
340374
const file = fs.createReadStream(app);
341-
return axios.put(uploadUrl, file, {
342-
maxContentLength: Infinity,
343-
maxBodyLength: Infinity,
344-
headers: {
375+
return putUploadWithRetry(uploadUrl,file, {
345376
'Content-Length': stats.size,
346-
'Content-Type': 'application/octet-stream',
347-
},
348-
transformRequest: [(d) => d],
349-
responseType: 'arraybuffer',
377+
'Content-Type': 'application/octet-stream',
350378
});
351379
}
352380

0 commit comments

Comments
 (0)