ingest::chainlink::eth_call_result made its eth_call HTTP request with no timeout, so the backtest_run on-chain Chainlink round-walk hung indefinitely on the free publicnode RPC. Fixed on the analysis worktree with a 12s timeout + 4 retries with backoff. Worth upstreaming to main — it makes any harness Chainlink walk reliable.
For Agents — the fix
- Symptom:
backtest_run’s on-chain Chainlink round-walk hangs forever on the free publicnode RPC.- Cause:
ingest::chainlink::eth_call_resulthad no reqwest timeout → a stalled/slow RPC response blocks with no deadline.- Fix (analysis worktree): add a reqwest 12s timeout + 4 retries with backoff to
eth_call_result. Upstream tomainso production/harness Chainlink reads share the hardening.- Next optimization (not yet done): the walk uses a fresh client per call (no connection reuse) → slow for long ranges; add connection pooling if long backtests are needed.
Symptoms
The backtest_run on-chain Chainlink round-walk (settlement label reconstruction) HUNG indefinitely on the free publicnode RPC — no progress, no error, no timeout.
Root cause
ingest::chainlink::eth_call_result issued the eth_call HTTP request with no reqwest timeout. A free public RPC that stalls (rate-limit, slow node, dropped connection) leaves the request with no deadline → the walk blocks forever on a single call.
Reusable gotcha
Any
eth_call/ RPC read against a free public RPC must carry an explicit HTTP timeout + retry. Production settlement uses the AlchemyPOLYGON_RPC_URL(reliable); the harness walk used free publicnode, where the missing timeout surfaced. The timeout is correct hygiene regardless of RPC.
Fix (analysis worktree)
Added to eth_call_result:
- reqwest 12s timeout — bounds each call so a stalled RPC can’t hang the walk.
- 4 retries with backoff — rides out transient free-RPC failures.
Result: any harness Chainlink round-walk is now reliable. Worth upstreaming to main — it hardens both the production settlement read and every backtest that walks Chainlink rounds.
Known remaining slowness (next optimization)
The walk creates a fresh HTTP client per call — no connection reuse. For long ranges this is slow (e.g. a week of BTC = too many sequential RPC calls, each paying fresh TLS/connection setup). Connection pooling (reuse a single reqwest::Client across the walk) is the next optimization if long-range backtests become a need. Not blocking today.
Related
- crypto-shortterm-backtesting — the validation harness this hardens (the on-chain round-walk feeds actual-resolution label reconstruction).
- crypto-shortterm-data-sources — Chainlink settlement is the on-chain Polygon read (production via Alchemy
POLYGON_RPC_URL; the harness walk used free publicnode). - crypto-shortterm-phase0-live-milestone — the live Chainlink on-chain read (~1s poll) this shares the call shape with.
- crypto-shortterm — project index.