feat(osti): recover missing-PDF articles with polite backoff retry#126
Open
vedant1711 wants to merge 2 commits into
Open
feat(osti): recover missing-PDF articles with polite backoff retry#126vedant1711 wants to merge 2 commits into
vedant1711 wants to merge 2 commits into
Conversation
OSTI's /servlets/purl/ endpoint rate-limits bursts of fulltext downloads with HTTP 503 or dropped connections; sampling showed 75/75 such failures succeed when refetched after a pause. Scrapy's built-in RetryMiddleware retries immediately, so it keeps hitting the same limit. Add BackoffRetryMiddleware, which waits with exponential backoff (plus jitter) before retrying 503/429 responses and dropped connections, and gives up after a configurable number of attempts so genuinely dead links are skipped and logged. DNS failures are left to the built-in RetryMiddleware so dead hosts fail fast. Enabled only in the OSTI spider's custom_settings; other spiders are unaffected. Also add opt-in OPEN_IRE_SKIP_EXISTING_REQUIRES_FILES (enabled for OSTI only): with OPEN_IRE_SKIP_EXISTING, known articles whose file download previously failed are re-processed instead of skipped, so missing PDFs get re-attempted on each run without re-downloading existing files.
…rawl DOIDuplicatesPipeline loads every existing DOI into a cache on open. On a re-crawl, an already-collected article's own DOI is in that cache, so the pipeline dropped the re-crawled item as a 'duplicate' of itself and appended a self-referential entry to extra.duplicate_sources. This blocked missing-PDF recovery entirely: with OPEN_IRE_SKIP_EXISTING + SKIP_EXISTING_REQUIRES_FILES, SkipExistingPipeline (priority 2) correctly lets a file-less article through, but DOIDuplicatesPipeline (priority 20) then dropped it before it reached the file-download pipeline (priority 100). Verified against the past OSTI run: pre-fix every re-crawled record was dropped; post-fix the file-less articles pass through to download. Skip the duplicate handling when the cached DOI owner is the same (repository, reference) as the incoming item. Cross-repository dedup is unchanged.
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.
Recovers fulltext PDFs for OSTI articles that previously failed to download, using polite retry within the normal spider run — no identity spoofing or WAF evasion.
Background
A prior OSTI crawl left ~6,800 articles without a stored PDF. Investigation showed most failures were HTTP 503 / dropped connections from OSTI's
/servlets/purl/endpoint rate-limiting bursts of downloads — not missing files. A sampled re-fetch after a pause recovered 75/75 of them as real PDFs served directly by OSTI. The remainder are genuine dead hosts (e.g.efw.bpa.govno longer resolves) or deliberate WAF blocks (403), which are correctly skipped rather than retried.Changes
1.
BackoffRetryMiddleware(new, enabled only in OSTIcustom_settings)503/429responses and dropped connections with exponential backoff + jitter, instead of Scrapy's immediate retries that keep hitting the same rate limit.403(WAF) and404pass straight through — no retries. DNS-dead hosts are left to the built-inRetryMiddlewareso they fail fast.2. Opt-in
OPEN_IRE_SKIP_EXISTING_REQUIRES_FILES(enabled for OSTI only)OPEN_IRE_SKIP_EXISTING, articles already in the DB that have a stored file are skipped, but file-less ones are re-processed so their PDF gets another attempt — without re-downloading the complete ones.3. Fix: don't drop an article as its own DOI duplicate on re-crawl (
DOIDuplicatesPipeline)(repository, reference)as the incoming item. Cross-repository dedup is unchanged. This is a general correctness fix; first-time crawls and cross-repo duplicates behave exactly as before.Scope / safety
custom_settings; no other spider's behavior changes.DOIDuplicatesPipelinefix touches a shared pipeline but only affects the previously-broken self-duplicate case; a second reviewer on that file is welcome.Testing
--skip-existing: complete articles skipped, file-less articles pass through to re-attempt, dead-host links skipped.Usage
Recovery run (against the DB holding the prior articles):