mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-10-26 05:56:14 +08:00
[files] Add retry with exponential backoff for file downloads in NM
Summary: See diff title Test Plan: Run locally, verify that we backoff on failure Reviewers: evan, spang, juan Reviewed By: juan Differential Revision: https://phab.nylas.com/D3887
This commit is contained in:
parent
31ae05fed2
commit
9c3dd29c10
2 changed files with 59 additions and 38 deletions
2
src/K2
2
src/K2
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3390bc0783d7f17906a6884e4d757876a337506f
|
Subproject commit 9f8aa0f42f031edc155a6e55d28edc6e008dc50c
|
||||||
|
|
@ -45,13 +45,18 @@ const THUMBNAIL_WIDTH = 320
|
||||||
export class Download {
|
export class Download {
|
||||||
static State = State
|
static State = State
|
||||||
|
|
||||||
constructor({accountId, fileId, targetPath, filename, filesize, progressCallback}) {
|
constructor({accountId, fileId, targetPath, filename, filesize, progressCallback, retryWithBackoff}) {
|
||||||
this.accountId = accountId;
|
this.accountId = accountId;
|
||||||
this.fileId = fileId;
|
this.fileId = fileId;
|
||||||
this.targetPath = targetPath;
|
this.targetPath = targetPath;
|
||||||
this.filename = filename;
|
this.filename = filename;
|
||||||
this.filesize = filesize;
|
this.filesize = filesize;
|
||||||
this.progressCallback = progressCallback;
|
this.progressCallback = progressCallback;
|
||||||
|
this.retryWithBackoff = retryWithBackoff || false;
|
||||||
|
this.timeout = 15000;
|
||||||
|
this.maxTimeout = 2 * 60 * 1000;
|
||||||
|
this.attempts = 0;
|
||||||
|
this.maxAttempts = 10;
|
||||||
if (!this.accountId) {
|
if (!this.accountId) {
|
||||||
throw new Error("Download.constructor: You must provide a non-empty accountId.");
|
throw new Error("Download.constructor: You must provide a non-empty accountId.");
|
||||||
}
|
}
|
||||||
|
|
@ -94,14 +99,22 @@ export class Download {
|
||||||
const stream = fs.createWriteStream(this.targetPath);
|
const stream = fs.createWriteStream(this.targetPath);
|
||||||
this.state = State.Downloading;
|
this.state = State.Downloading;
|
||||||
|
|
||||||
|
let startRequest = null;
|
||||||
|
|
||||||
const onFailed = (err) => {
|
const onFailed = (err) => {
|
||||||
this.request = null;
|
this.request = null;
|
||||||
stream.end();
|
stream.end();
|
||||||
|
if (!this.retryWithBackoff || this.attempts >= this.maxAttempts) {
|
||||||
this.state = State.Failed;
|
this.state = State.Failed;
|
||||||
if (fs.existsSync(this.targetPath)) {
|
if (fs.existsSync(this.targetPath)) {
|
||||||
fs.unlinkSync(this.targetPath);
|
fs.unlinkSync(this.targetPath);
|
||||||
}
|
}
|
||||||
reject(err);
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.timeout = Math.min(this.maxTimeout, this.timeout * 2);
|
||||||
|
startRequest();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSuccess = () => {
|
const onSuccess = () => {
|
||||||
|
|
@ -112,6 +125,8 @@ export class Download {
|
||||||
resolve(this);
|
resolve(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
startRequest = () => {
|
||||||
|
console.info(`starting download with ${this.timeout}ms timeout`);
|
||||||
const request = new NylasAPIRequest({
|
const request = new NylasAPIRequest({
|
||||||
api: NylasAPI,
|
api: NylasAPI,
|
||||||
options: {
|
options: {
|
||||||
|
|
@ -119,7 +134,9 @@ export class Download {
|
||||||
path: `/files/${this.fileId}/download`,
|
path: `/files/${this.fileId}/download`,
|
||||||
accountId: this.accountId,
|
accountId: this.accountId,
|
||||||
encoding: null, // Tell `request` not to parse the response data
|
encoding: null, // Tell `request` not to parse the response data
|
||||||
|
timeout: this.timeout,
|
||||||
started: (req) => {
|
started: (req) => {
|
||||||
|
this.attempts += 1;
|
||||||
this.request = req;
|
this.request = req;
|
||||||
return progress(this.request, {throtte: 250})
|
return progress(this.request, {throtte: 250})
|
||||||
.on('progress', (prog) => {
|
.on('progress', (prog) => {
|
||||||
|
|
@ -150,6 +167,9 @@ export class Download {
|
||||||
});
|
});
|
||||||
|
|
||||||
request.run()
|
request.run()
|
||||||
|
};
|
||||||
|
|
||||||
|
startRequest();
|
||||||
});
|
});
|
||||||
return this.promise
|
return this.promise
|
||||||
}
|
}
|
||||||
|
|
@ -233,6 +253,7 @@ class FileDownloadStore extends NylasStore {
|
||||||
filename: file.displayName(),
|
filename: file.displayName(),
|
||||||
targetPath,
|
targetPath,
|
||||||
progressCallback: () => this.trigger(),
|
progressCallback: () => this.trigger(),
|
||||||
|
retryWithBackoff: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Do we actually need to queue and run the download? Queuing a download
|
// Do we actually need to queue and run the download? Queuing a download
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue