Skip to content

Commit 14cc519

Browse files
Enhance retry logic for batch requests in ExtendedAsyncHTTPProvider (#176)
* Enhance ExtendedAsyncHTTPProvider with retry logic for batch requests * Bump version to v0.12.4
1 parent f831232 commit 14cc519

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "sw-utils"
3-
version = "v0.12.3"
3+
version = "v0.12.4"
44
description = "StakeWise Python utils"
55
authors = ["StakeWise Labs <info@stakewise.io>"]
66
license = "GPL-3.0-or-later"

sw_utils/execution.py

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ def __init__(
6565
super().__init__(endpoint_uri=URI(endpoint_urls[0]))
6666

6767
async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
68+
"""
69+
Request with retries and fallback endpoints.
70+
"""
6871
if self.retry_timeout:
6972

7073
def custom_before_log(retry_state: 'RetryCallState') -> None:
@@ -78,11 +81,13 @@ def custom_before_log(retry_state: 'RetryCallState') -> None:
7881
self.retry_timeout,
7982
before=custom_before_log,
8083
)
81-
return await retry_decorator(self.make_request_inner)(method, params)
84+
return await retry_decorator(self.make_request_with_fallback_endpoints)(method, params)
8285

83-
return await self.make_request_inner(method, params)
86+
return await self.make_request_with_fallback_endpoints(method, params)
8487

85-
async def make_request_inner(self, method: RPCEndpoint, params: Any) -> RPCResponse:
88+
async def make_request_with_fallback_endpoints(
89+
self, method: RPCEndpoint, params: Any
90+
) -> RPCResponse:
8691
for i, provider in enumerate(self._providers):
8792
is_last_iteration = i == len(self._providers) - 1
8893
try:
@@ -106,6 +111,51 @@ async def make_request_inner(self, method: RPCEndpoint, params: Any) -> RPCRespo
106111

107112
return {}
108113

114+
async def make_batch_request(
115+
self, batch_requests: list[tuple[RPCEndpoint, Any]]
116+
) -> list[RPCResponse] | RPCResponse:
117+
"""
118+
Batch request with retries and fallback endpoints.
119+
"""
120+
if self.retry_timeout:
121+
122+
def custom_before_log(retry_state: 'RetryCallState') -> None:
123+
if retry_state.attempt_number <= 1:
124+
return
125+
msg = 'Retrying execution batch request, attempt %s'
126+
args = (retry_state.attempt_number,)
127+
logger.log(logging.INFO, msg, *args)
128+
129+
retry_decorator = retry_aiohttp_errors(
130+
self.retry_timeout,
131+
before=custom_before_log,
132+
)
133+
return await retry_decorator(self.make_batch_request_with_fallback_endpoints)(
134+
batch_requests
135+
)
136+
137+
return await self.make_batch_request_with_fallback_endpoints(batch_requests)
138+
139+
async def make_batch_request_with_fallback_endpoints(
140+
self, batch_requests: list[tuple[RPCEndpoint, Any]]
141+
) -> list[RPCResponse] | RPCResponse:
142+
for i, provider in enumerate(self._providers):
143+
is_last_iteration = i == len(self._providers) - 1
144+
try:
145+
response = await provider.make_batch_request(batch_requests)
146+
# No special error handling for batch, just fallback on exception
147+
return response
148+
except Exception as error:
149+
if not can_be_retried_aiohttp_error(error):
150+
raise error
151+
152+
if is_last_iteration:
153+
raise error
154+
155+
logger.warning('%s: %s', provider.endpoint_uri, repr(error))
156+
157+
return []
158+
109159
def set_retry_timeout(self, retry_timeout: int) -> None:
110160
self.retry_timeout = retry_timeout
111161

0 commit comments

Comments
 (0)