You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Retry failed harvest requests, and fail loudly when they don't recover
Both response classes rescued every error while paging, nil'd the
response, and left their loop, so #index returned normally after a single
transient failure: a harvest that indexed 6 of 15 documents exited 0 and
looked like a success. Individual document failures were dropped the same
way, by compacting them out of the page.
Requests now go through retries with an exponential backoff for failures
that tend to be transient -- connection resets, broken pipes, timeouts,
TLS errors, 5xx, rate limiting -- and a request that still can't be
completed raises GeoCombine::Exceptions::HarvestError. A 404 for a single
document is logged and skipped instead, since a record can be indexed but
unreadable.
Responses are checked rather than trusted, since a status code alone
can't tell a page of records from a rejection:
- a 200 carrying HTML, or any body that isn't a JSON object, is treated
as a failure worth retrying rather than parsed as a document
- every page is validated as a page of search results, not just the
first one through the response factory; a 200 carrying JSON that
isn't one used to read as "no more results" and end the harvest
- a result with no link to itself, and a page whose every document was
skipped, are logged rather than quietly dropped
Closes#208
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
headers: { 'X-Api-Key' => 'secret' }, # SITE1 only
@@ -201,6 +203,12 @@ Be aware that this makes a harvest take considerably longer than it did when the
201
203
202
204
Headers can be configured either globally for all sites or on a per-site basis, and are sent with every request the harvester makes; headers configured for a site are merged over the global ones. This is one way to get the harvester past a firewall or bot detection (at Stanford, for example, requests carrying a particular header skip Turnstile), and it can also be used to authenticate the harvester. Configuring a `User-Agent` is worthwhile even if you need neither: it identifies your harvester to the sites you harvest, and lets GeoBlacklight's `crawler_detector` recognize it as a bot.
203
205
206
+
##### Retries (default: 3 retries, starting with a 2 second delay)
207
+
208
+
Requests that fail in ways that tend to be transient are retried with an exponential backoff: connection resets, broken pipes, timeouts, TLS errors, 5xx responses, rate limiting, and responses that come back with a 200 but aren't JSON (bot mitigation often answers a crawler with a page of HTML). How many times to retry and the delay to start doubling from can be configured globally or per site with `max_retries` and `retry_delay`.
209
+
210
+
A request that still can't be completed raises `GeoCombine::Exceptions::HarvestError`, so a harvest that couldn't finish exits non-zero instead of looking like a success that happened to index part of the site. Every page of results is checked, not just the first: a 200 whose JSON isn't a page of search results, which is how a WAF or API gateway rejection often arrives, raises rather than reading as the end of the results. The one failure that is logged and skipped instead is a 404 for an individual document, since a record can be indexed but unreadable.
0 commit comments