Don't retry failing custom Find Full Text resolvers

A custom resolver returning a 429/5xx inherited Zotero.HTTP's default
retry policy, which could cause the whole queue to stall for up to an
hour -- or indefinitely for a Retry-After -- on a dead resolver, despite
the 5-second timeout on the request.

https://forums.zotero.org/discussion/133642/
This commit is contained in:
Dan Stillman 2026-09-08 11:25:17 -04:00
parent 364181f4e7
commit 9b769d3987
2 changed files with 75 additions and 1 deletions

View file

@ -1401,7 +1401,12 @@ Zotero.Attachments = new function () {
url,
{
responseType: mode == 'json' ? 'json' : 'document',
timeout: 5000
timeout: 5000,
// Move on to the next resolver instead of waiting on a
// failing third-party server, which blocks the rest of
// the queue
errorDelayMax: 0,
noRetryOnThrottle: true
}
);

View file

@ -1489,6 +1489,75 @@ describe("Zotero.Attachments", function () {
assert.equal(json.filename, 'Test.pdf');
assert.equal(await OS.File.stat(attachment.getFilePath()).size, pdfSize);
});
it("should not retry a custom resolver that returns a server error", async function () {
var doi = doi4;
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
item.setField('title', 'Test');
item.setField('DOI', doi);
await item.saveTx();
var requests = 0;
httpd.registerPathHandler(
"/failing/" + doi,
{
handle: function (request, response) {
requests++;
response.setStatusLine(null, 500, "Internal Server Error");
}
}
);
var resolvers = [{
name: 'Custom',
method: 'get',
url: baseURL + "failing/{doi}",
mode: 'html',
selector: '#pdf-link',
attribute: 'href'
}];
Zotero.Prefs.set('findPDFs.resolvers', JSON.stringify(resolvers));
var attachment = await Zotero.Attachments.addAvailableFile(item);
assert.isFalse(attachment);
assert.equal(requests, 1);
});
it("should not honor Retry-After from a custom resolver", async function () {
var doi = doi4;
var item = createUnsavedDataObject('item', { itemType: 'journalArticle' });
item.setField('title', 'Test');
item.setField('DOI', doi);
await item.saveTx();
var requests = 0;
httpd.registerPathHandler(
"/throttled/" + doi,
{
handle: function (request, response) {
requests++;
response.setStatusLine(null, 429, "Too Many Requests");
response.setHeader("Retry-After", "3600");
}
}
);
var resolvers = [{
name: 'Custom',
method: 'get',
url: baseURL + "throttled/{doi}",
mode: 'html',
selector: '#pdf-link',
attribute: 'href'
}];
Zotero.Prefs.set('findPDFs.resolvers', JSON.stringify(resolvers));
var attachment = await Zotero.Attachments.addAvailableFile(item);
assert.isFalse(attachment);
assert.equal(requests, 1);
});
});
describe("#getFileBaseNameFromItem()", function () {