request.py 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. from typing import Any, Callable, Type
  2. import requests
  3. from requests.exceptions import ConnectionError, Timeout
  4. from tenacity import (
  5. retry,
  6. retry_if_exception,
  7. retry_if_exception_type,
  8. stop_after_delay,
  9. wait_exponential,
  10. )
  11. from openhands.utils.tenacity_stop import stop_if_should_exit
  12. def is_server_error(exception):
  13. return (
  14. isinstance(exception, requests.HTTPError)
  15. and exception.response.status_code >= 500
  16. )
  17. def is_404_error(exception):
  18. return (
  19. isinstance(exception, requests.HTTPError)
  20. and exception.response.status_code == 404
  21. )
  22. DEFAULT_RETRY_EXCEPTIONS = [
  23. ConnectionError,
  24. Timeout,
  25. ]
  26. def send_request(
  27. session: requests.Session,
  28. method: str,
  29. url: str,
  30. retry_exceptions: list[Type[Exception]] | None = None,
  31. retry_fns: list[Callable[[Exception], bool]] | None = None,
  32. timeout: int = 120,
  33. **kwargs: Any,
  34. ) -> requests.Response:
  35. exceptions_to_catch = retry_exceptions or DEFAULT_RETRY_EXCEPTIONS
  36. retry_condition = retry_if_exception_type(
  37. tuple(exceptions_to_catch)
  38. ) | retry_if_exception(is_server_error)
  39. if retry_fns is not None:
  40. for fn in retry_fns:
  41. retry_condition |= retry_if_exception(fn)
  42. kwargs["timeout"] = timeout
  43. @retry(
  44. stop=stop_after_delay(timeout) | stop_if_should_exit(),
  45. wait=wait_exponential(multiplier=1, min=4, max=60),
  46. retry=retry_condition,
  47. reraise=True,
  48. )
  49. def _send_request_with_retry():
  50. response = session.request(method, url, **kwargs)
  51. response.raise_for_status()
  52. return response
  53. return _send_request_with_retry()