fix(anilist): stop requeueing searches that matched nothing

A well-formed search returning zero media is deterministic for that title, so
the retry queue just burns rate limit against it. Transient failures (network,
GraphQL errors, malformed data) throw inside the query executor and are still
caught as retryable, so only genuine no-matches become non-retryable.
This commit is contained in:
2026-07-28 02:27:36 -07:00
parent 9f85c55d23
commit 59c305e023
2 changed files with 37 additions and 1 deletions
@@ -605,3 +605,33 @@ test('updateAnilistPostWatchProgress returns error when search fails', async ()
globalThis.fetch = originalFetch;
}
});
test('updateAnilistPostWatchProgress does not requeue a search that matched nothing', async () => {
const originalFetch = globalThis.fetch;
globalThis.fetch = (async () =>
createJsonResponse({ data: { Page: { media: [] } } })) as typeof fetch;
try {
const result = await updateAnilistPostWatchProgress('token', 'Unknown Show', 3);
assert.equal(result.status, 'error');
assert.equal(result.retryable, false);
assert.match(result.message, /no matches/i);
} finally {
globalThis.fetch = originalFetch;
}
});
test('updateAnilistPostWatchProgress still allows retry when the search itself fails', async () => {
const originalFetch = globalThis.fetch;
globalThis.fetch = (async () =>
createJsonResponse({ errors: [{ message: 'upstream exploded' }] })) as typeof fetch;
try {
const result = await updateAnilistPostWatchProgress('token', 'Demo Show', 3);
assert.equal(result.status, 'error');
assert.notEqual(result.retryable, false);
assert.match(result.message, /search failed/i);
} finally {
globalThis.fetch = originalFetch;
}
});
+7 -1
View File
@@ -305,7 +305,13 @@ export async function updateAnilistPostWatchProgress(
}
if (!resolution) {
return { status: 'error', message: 'AniList search returned no matches.' };
// A well-formed search that matched nothing is deterministic for this title, so
// requeueing it just burns rate limit. Transient failures throw and are caught above.
return {
status: 'error',
retryable: false,
message: 'AniList search returned no matches.',
};
}
if (!resolution.seasonResolved) {
// Updating the season 1 entry here is worse than not updating at all.