Skip to content

fetch: add retry/backoff and endpoint resilience#21

Merged
blackopsrepl merged 1 commit intomainfrom
issue/8-add-overpass-retries-and-fallback
Mar 21, 2026
Merged

fetch: add retry/backoff and endpoint resilience#21
blackopsrepl merged 1 commit intomainfrom
issue/8-add-overpass-retries-and-fallback

Conversation

@blackopsrepl
Copy link
Copy Markdown
Contributor

Summary

Overpass fetches still used a single endpoint and a single request attempt, so transient rate limits or endpoint outages failed the whole load with limited context.

This change adds configurable resilience to the live fetch path:

  • NetworkConfig now supports endpoint pools, retry count, and retry backoff
  • transient HTTP and request failures are retried with backoff
  • multiple endpoints are tried in order, with contextual error messages across attempts
  • local tests cover both retry-on-429 and fallback-to-secondary-endpoint behavior

Validation

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test

Fixes #8

@blackopsrepl blackopsrepl merged commit 5d48e5d into main Mar 21, 2026
2 of 3 checks passed
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 982f66e1af

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +538 to +542
fn overpass_endpoints(config: &NetworkConfig) -> Vec<String> {
if config.overpass_endpoints.is_empty() {
vec![config.overpass_url.clone()]
} else {
config.overpass_endpoints.clone()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Respect overpass_url when callers keep the default endpoint list

NetworkConfig still exposes overpass_url as a public field, so downstream code can validly do let mut cfg = NetworkConfig::default(); cfg.overpass_url = mirror.into(); or NetworkConfig { overpass_url: ..., ..Default::default() }. After this change, overpass_endpoints() ignores that override whenever overpass_endpoints is non-empty, and Default now always pre-populates the list with overpass-api.de. That creates a silent regression for existing custom-endpoint users: requests continue going to the default host unless they learn to update both fields.

Useful? React with 👍 / 👎.

Comment on lines +483 to +494
return response
.bytes()
.await
.map(|bytes| bytes.to_vec())
.map_err(|error| {
RoutingError::Network(format!(
"Overpass response body read failed from {} on attempt {}: {}",
endpoint,
attempt + 1,
error
))
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retry body-read failures instead of aborting after a 200 response

Once an endpoint returns HTTP 200, this branch immediately returns the result of response.bytes().await. If the body download itself times out or the connection is reset mid-stream—which can happen on large Overpass payloads under the configured read_timeout—the function exits here and never reaches the retry loop or the secondary endpoints. In those cases the new resilience logic still fails on the first mirror instead of retrying/failing over.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fetch: add retry/backoff and endpoint resilience for Overpass requests

1 participant