Skip to content

Commit d68747c

Browse files
Issue #441 Add retry function borrowed from openeo-python-driver
1 parent a2ff467 commit d68747c

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

openeo/rest/http.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from typing import Set
2+
3+
import requests
4+
import requests.adapters
5+
6+
MAX_RETRIES = 3
7+
8+
9+
def requests_with_retry(
10+
total: int = MAX_RETRIES,
11+
read: int = MAX_RETRIES,
12+
other: int = MAX_RETRIES,
13+
status: int = MAX_RETRIES,
14+
backoff_factor: float = 1,
15+
status_forcelist: Set[int] = frozenset([429, 500, 502, 503, 504]),
16+
**kwargs,
17+
) -> requests.Session:
18+
"""
19+
Create a `requests.Session` with automatic retrying
20+
21+
Inspiration and references:
22+
- https://requests.readthedocs.io/en/latest/api/#requests.adapters.HTTPAdapter
23+
- https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html#urllib3.util.Retry
24+
- https://findwork.dev/blog/advanced-usage-python-requests-timeouts-retries-hooks/#retry-on-failure
25+
"""
26+
session = requests.Session()
27+
retry = requests.adapters.Retry(
28+
total=total,
29+
read=read,
30+
other=other,
31+
status=status,
32+
backoff_factor=backoff_factor,
33+
status_forcelist=status_forcelist,
34+
**kwargs,
35+
)
36+
adapter = requests.adapters.HTTPAdapter(max_retries=retry)
37+
session.mount("http://", adapter)
38+
session.mount("https://", adapter)
39+
return session

setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"flake8>=5.0.0",
2929
"time_machine",
3030
"pyproj>=3.2.0", # Pyproj is an optional, best-effort runtime dependency
31+
"re-assert",
3132
]
3233

3334
docs_require = [

tests/rest/test_http.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import logging
2+
3+
import pytest
4+
import requests.exceptions
5+
from re_assert import Matches
6+
7+
from openeo.rest.http import requests_with_retry
8+
9+
10+
def test_requests_with_retry(caplog):
11+
"""Simple test for retrying using an invalid domain."""
12+
caplog.set_level(logging.DEBUG)
13+
14+
session = requests_with_retry(total=2, backoff_factor=0.1)
15+
with pytest.raises(requests.exceptions.ConnectionError, match="Max retries exceeded"):
16+
_ = session.get("https://example.test")
17+
18+
assert caplog.messages == [
19+
"Starting new HTTPS connection (1): example.test:443",
20+
Matches("Incremented Retry.*Retry\(total=1"),
21+
# Matches("Retrying.*total=1.*Failed to establish a new connection"),
22+
Matches("Retrying.*total=1.*Failed to resolve 'example.test'"),
23+
"Starting new HTTPS connection (2): example.test:443",
24+
Matches("Incremented Retry.*Retry\(total=0"),
25+
Matches("Retrying.*total=0.*Failed to resolve 'example.test'"),
26+
"Starting new HTTPS connection (3): example.test:443",
27+
]
28+
29+
30+
def test_requests_with_retry_zero(caplog):
31+
"""Simple test for retrying using an invalid domain."""
32+
caplog.set_level(logging.DEBUG)
33+
34+
session = requests_with_retry(total=0)
35+
with pytest.raises(requests.exceptions.ConnectionError, match="Max retries exceeded"):
36+
_ = session.get("https://example.test")
37+
38+
assert caplog.messages == [
39+
"Starting new HTTPS connection (1): example.test:443",
40+
]

0 commit comments

Comments
 (0)