fix: add retry on polymarket's _get_market so a transient server error does not break the job#226
Conversation
19b6d37 to
88291b3
Compare
|
@CodeRabbit full review |
✅ Action performedFull review finished. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds exponential backoff retry handling to ChangesBackoff Retry for Market Fetch
Estimated code review effort: 1 (Trivial) | ~5 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/sources/polymarket.py (1)
294-322: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winAdd a timeout to the Polymarket API calls here
backoff.on_exceptiononly retries raisedRequestExceptions; withouttimeout, a stalledrequests.getcan block forever and never reach the retry path. Apply the same timeout to the other Polymarketrequests.getcalls in this module too.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/sources/polymarket.py` around lines 294 - 322, The Polymarket API calls in `_get_market` can hang indefinitely because `requests.get` has no timeout, so the backoff retry never triggers on a stalled request. Add a timeout to the `requests.get` calls in `_get_market` and apply the same timeout pattern to the other Polymarket request methods in this module so all network calls fail fast and can be retried by `backoff.on_exception`.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/sources/polymarket.py`:
- Around line 294-322: The Polymarket API calls in `_get_market` can hang
indefinitely because `requests.get` has no timeout, so the backoff retry never
triggers on a stalled request. Add a timeout to the `requests.get` calls in
`_get_market` and apply the same timeout pattern to the other Polymarket request
methods in this module so all network calls fail fast and can be retried by
`backoff.on_exception`.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: aa061c8d-5be2-49ae-8bdc-d2ab5749def4
📒 Files selected for processing (2)
src/sources/polymarket.pysrc/tests/test_polymarket.py
88291b3 to
499a593
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/tests/test_polymarket.py`:
- Around line 567-568: The retry test is patching the wrong sleep target, so the
backoff pause still occurs during retries. Update the test around the polymarket
request retry path to patch backoff’s actual sleep call via
backoff._sync.time.sleep (or patch time.sleep globally) instead of
sources.polymarket.time.sleep, keeping the test fast while preserving the
existing requests.get mock and retry assertions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 936abf01-4449-4dc2-8803-7b5afd71a7b3
📒 Files selected for processing (2)
src/sources/polymarket.pysrc/tests/test_polymarket.py
🚧 Files skipped from review as they are similar to previous changes (1)
- src/sources/polymarket.py
| @patch("sources.polymarket.time.sleep") | ||
| @patch("sources.polymarket.requests.get") |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify how backoff's sync module performs its sleep call
python -c "import backoff._sync, inspect; print(inspect.getsource(backoff._sync))" 2>/dev/null | grep -n "sleep\|^import\|^from"Repository: forecastingresearch/forecastbench
Length of output: 171
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== src/tests/test_polymarket.py (around lines 550-590) ==\n'
sed -n '540,600p' src/tests/test_polymarket.py | cat -n
printf '\n== src/sources/polymarket.py (search for _get_market, time, backoff) ==\n'
rg -n "def _get_market|backoff|time\.sleep|import time|requests.get" src/sources/polymarket.py
printf '\n== src/sources/polymarket.py (around _get_market) ==\n'
sed -n '1,220p' src/sources/polymarket.py | cat -n
printf '\n== backoff package sleep implementation (if installed) ==\n'
python3 - <<'PY'
import inspect, sys
try:
import backoff._sync as s
print(inspect.getsource(s))
except Exception as e:
print(type(e).__name__ + ":", e)
sys.exit(0)
PY
printf '\n== project dependency pins for backoff ==\n'
rg -n "backoff" pyproject.toml requirements*.txt setup.cfg setup.py poetry.lock Pipfile.lock 2>/dev/null || trueRepository: forecastingresearch/forecastbench
Length of output: 14643
🌐 Web query:
backoff _sync.py sleep time.sleep import source GitHub
💡 Result:
In the Python backoff library, the backoff/_sync.py source file manages synchronous retry loops, including the implementation of wait intervals [1][2]. The library uses time.sleep(seconds) to pause execution between retry attempts [2]. When a retry condition is met (e.g., an exception is raised or a predicate is truthy), the library calculates the next wait time and performs a blocking sleep: python # Simplified logic from backoff/_sync.py seconds = _next_wait(wait, e, jitter, elapsed, max_time_value) # ... time.sleep(seconds) Because backoff relies on the standard time.sleep() for its synchronous decorators, you can mock or monkey-patch it during testing if you need to bypass the delays [3]. Common testing patterns include using unittest.mock.patch to intercept backoff._sync.time.sleep [3]. For asynchronous code, backoff handles waiting differently, typically using asyncio.sleep() instead of time.sleep(), as time.sleep() would block the entire event loop [4][5]. You can find the implementation details for asynchronous retries in backoff/_async.py [2].
Citations:
- 1: https://github.com/litl/backoff/blob/master/backoff/_sync.py
- 2: litl/backoff@v2.1.2...v2.2.1
- 3: Question: Unit Testing a Decorated Function with max_time litl/backoff#54
- 4: https://github.com/python-backoff/backoff/
- 5: https://pypi.org/project/python-backoff/
Patch the retry sleep target.
backoff sleeps through its own backoff._sync.time.sleep, so sources.polymarket.time.sleep won’t suppress the retry pause here. Patch backoff._sync.time.sleep (or time.sleep globally) to keep this test fast.
🧰 Tools
🪛 ast-grep (0.44.1)
[info] 567-567: no timeout was given on call to external resource
Context: patch("sources.polymarket.requests.get")
Note: [CWE-1088] Synchronous Access of Remote Resource without Timeout.
(requests-timeout)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/tests/test_polymarket.py` around lines 567 - 568, The retry test is
patching the wrong sleep target, so the backoff pause still occurs during
retries. Update the test around the polymarket request retry path to patch
backoff’s actual sleep call via backoff._sync.time.sleep (or patch time.sleep
globally) instead of sources.polymarket.time.sleep, keeping the test fast while
preserving the existing requests.get mock and retry assertions.
…ror does not break the job
499a593 to
60343bb
Compare
Summary by CodeRabbit
Bug Fixes
Tests