Spaces:
Sleeping
Sleeping
File size: 1,446 Bytes
dbf7313 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | from __future__ import annotations
import http.client
import socket
import time
import urllib.error
import urllib.request
from collections.abc import Callable
from typing import Any
TRANSIENT_HTTP_ERRORS = (
TimeoutError,
socket.timeout,
urllib.error.URLError,
http.client.RemoteDisconnected,
ConnectionResetError,
)
def urlopen_with_retry(
request: urllib.request.Request | str,
*,
timeout: int,
max_retries: int = 5,
log: Callable[[str], None] | None = None,
label: str | None = None,
opener: Callable[..., Any] | None = None,
sleep: Callable[[float], None] = time.sleep,
) -> Any:
attempt = 0
target = label or (request if isinstance(request, str) else request.full_url)
opener = opener or urllib.request.urlopen
while True:
try:
return opener(request, timeout=timeout)
except urllib.error.HTTPError:
raise
except TRANSIENT_HTTP_ERRORS as exc:
attempt += 1
if attempt > max_retries:
raise RuntimeError(
f"HTTP request failed after {max_retries} retries: {target} {exc}"
) from exc
sleep_for = min(2**attempt, 30)
if log is not None:
log(
f"Transient network failure for {target} (attempt {attempt}/{max_retries}); retrying in {sleep_for}s"
)
sleep(sleep_for)
|