fix: survive stalled requests during batch fetches - #82
Merged
Conversation
A single stalled fetch() inside _fetch_batch's execute_async_script hung the whole script until Selenium's 120s script timeout fired, and the TimeoutException propagated uncaught out of fetch_all — killing a multi-year full sync partway through (observed in year 2 of 10). Two layers of defense: - Every in-page fetch now carries AbortSignal.timeout(60s), so a stalled request degrades to one skipped endpoint instead of hanging the script. - _fetch_batch retries the batch up to 3 times on WebDriverException, then loudly skips it so the sync continues; a re-run fills the gap. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A full 10-year sync died in year 2 with
selenium.common.exceptions.TimeoutException: Message: script timeoutpropagating out offetch_all→_fetch_batch. Root cause: the in-page JS awaits all endpoint fetches with no per-request timeout, so one stalledfetch()hangs the async script until Selenium's 120s script timeout kills it — and no call site catches the exception, so the whole sync crashes.Two layers of defense:
fetch()(REST and GraphQL) now carriesAbortSignal.timeout(60000). A stalled request now resolves as a per-endpoint error — already tolerated by all callers — instead of hanging the script._fetch_batchretries up to 3× onWebDriverException(10s apart), then prints a loud warning and skips the batch so a long sync keeps going; the sync is upsert-based, so a re-run fills any skipped gap.Tests (watched fail first): retry-then-succeed, persistent-failure-returns-empty, and a guard that the in-page fetches keep their AbortSignal timeout. Full suite: 254 passed, ruff clean.
🤖 Generated with Claude Code