Skip to content

Added retry mechanism for requests#223

Merged
popenta merged 4 commits intofeat/nextfrom
retry-mechanism-get-requests
Apr 2, 2025
Merged

Added retry mechanism for requests#223
popenta merged 4 commits intofeat/nextfrom
retry-mechanism-get-requests

Conversation

@popenta
Copy link
Collaborator

@popenta popenta commented Apr 1, 2025

No description provided.

@popenta popenta self-assigned this Apr 1, 2025
@github-actions
Copy link

github-actions bot commented Apr 1, 2025

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  multiversx_sdk/network_providers
  __init__.py
  api_network_provider.py
  config.py
  proxy_network_provider.py
Project Total  

This report was generated by python-coverage-comment-action

adapter = HTTPAdapter(max_retries=retry_strategy)

with requests.Session() as session:
session.mount("https://", adapter)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might not be reliable at times. E.g. when the developer is using a local proxy.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also added:

session.mount("http://", adapter)

Comment on lines 295 to 297
total=self.config.requests_options.get("retries"),
backoff_factor=self.config.requests_options.get("backoff_factor", 0),
status_forcelist=self.config.requests_options.get("status_forcelist"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The developer might mistakenly believe that retries and backoff_factor etc. are requests options (since they are passed as config.requests_options). This is not entirely true, and might cause confusion.

Alternative:

self.config.requests_retry_options.get("total")
self.config.requests_retry_options.get("backoff_factor")
...

Or even:

self.config.requests_retry_options.total
self.config.requests_retry_options.backoff_factor
...

💡

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

except Exception as err:
raise NetworkProviderError(url, err)

def _remove_unneeded_options_for_request(self) -> dict[str, Any]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hack / workaround can be removed if we use the approach with separate retry options.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

def _do_post(self, url: str, payload: Any) -> dict[str, Any]:
try:
response = requests.post(url, json=payload, **self.config.requests_options)
request_options = self._remove_unneeded_options_for_request()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hack / workaround can be reverted etc.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

def _do_get(self, url: str) -> GenericResponse:
try:
response = requests.get(url, **self.config.requests_options)
retry_strategy = Retry(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above.

andreibancioiu
andreibancioiu previously approved these changes Apr 1, 2025
class RequestsRetryOptions:
retries: int = 3
backoff_factor: float = 0.05
status_forecelist: list[int] = field(default_factory=lambda: [500, 502, 503, 504])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They seem fine. If there are constants in Python standard library, we can use them.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaced with constants


adapter = HTTPAdapter(max_retries=retry_strategy)

with requests.Session() as session:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully, no performance overhead with creating a lot of ephemeral Session objects 🤞

We should keep an eye on this matter.

Comment on lines +368 to +377
total=self.config.requests_retry_options.retries,
backoff_factor=self.config.requests_retry_options.backoff_factor,
status_forcelist=self.config.requests_retry_options.status_forecelist,
)

adapter = HTTPAdapter(max_retries=retry_strategy)

with requests.Session() as session:
session.mount("https://", adapter)
session.mount("http://", adapter)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little bit of duplication. In the future, maybe we can extract something to shared.py - but only if it really makes sense.

@popenta popenta merged commit be08ac9 into feat/next Apr 2, 2025
6 checks passed
@popenta popenta deleted the retry-mechanism-get-requests branch April 2, 2025 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants