From a9c10309f7fb8cfca0e5af796fac2a1644f80cad Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Sun, 29 Sep 2019 04:01:33 -0400 Subject: [PATCH] Detect TimeoutException during ZFS S3 upload We're not currently setting a timeout, so this shouldn't happen, but someone [1] is getting a timeout error with undefined ms and NS_BINDING_ABORTED from the channel. It also happened during a /fulltext upload, so it's not limited to S3, but this fix should give a more helpful error message for such errors during file syncing. [1] https://forums.zotero.org/discussion/79286/ --- chrome/content/zotero/xpcom/http.js | 2 +- chrome/content/zotero/xpcom/storage/zfs.js | 24 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/chrome/content/zotero/xpcom/http.js b/chrome/content/zotero/xpcom/http.js index 68de9a4db0..856a173f95 100644 --- a/chrome/content/zotero/xpcom/http.js +++ b/chrome/content/zotero/xpcom/http.js @@ -87,7 +87,7 @@ Zotero.HTTP = new function() { this.CancelledException.prototype = Object.create(Error.prototype); this.TimeoutException = function(ms) { - this.message = "XMLHttpRequest has timed out after " + ms + "ms"; + this.message = "XMLHttpRequest has timed out" + (ms ? ` after ${ms} ms` : ""); this.stack = new Error().stack; }; this.TimeoutException.prototype = Object.create(Error.prototype); diff --git a/chrome/content/zotero/xpcom/storage/zfs.js b/chrome/content/zotero/xpcom/storage/zfs.js index 480ac979be..6c11960535 100644 --- a/chrome/content/zotero/xpcom/storage/zfs.js +++ b/chrome/content/zotero/xpcom/storage/zfs.js @@ -683,6 +683,30 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = { return this._uploadFile(request, item, params); } } + // Alternative to the above. There was at least one report of this happening even though + // a timeout isn't being set, with 2152398850 (NS_BINDING_ABORTED) from the channel: + // https://forums.zotero.org/discussion/79286/ + else if (e instanceof Zotero.HTTP.TimeoutException) { + Zotero.logError(e); + if (this._s3ConsecutiveFailures >= this._maxS3ConsecutiveFailures) { + Zotero.debug(this._s3ConsecutiveFailures + + " consecutive S3 failures -- aborting", 1); + this._s3ConsecutiveFailures = 0; + let e = Zotero.getString('sync.storage.error.zfs.restart', Zotero.appName); + throw new Error(e); + } + else { + Zotero.logError("S3 timed out (" + item.libraryKey + ") -- retrying upload"); + if (this._s3Backoff < this._maxS3Backoff) { + this._s3Backoff *= 2; + } + this._s3ConsecutiveFailures++; + Zotero.debug("Delaying " + item.libraryKey + " upload for " + + this._s3Backoff + " seconds", 2); + yield Zotero.Promise.delay(this._s3Backoff * 1000); + return this._uploadFile(request, item, params); + } + } else if (e.status == 500) { // TODO: localize throw new Error("File upload failed. Please try again.");