Skip to content

Commit fe2ef76

Browse files
committed
retry aiohttp requests on ClientConnectionError
The aiohttp_retry library appears not to retry any raised Exceptions by default. Retry aiohttp.ClientConnectionError to prevent failed requests on intermittent Nexus connection issues. Signed-off-by: Taylor Madore <[email protected]>
1 parent 81e886b commit fe2ef76

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

cachito/workers/pkg_managers/general_js.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ async def on_request_start(
140140

141141
trace_config = aiohttp.TraceConfig()
142142
trace_config.on_request_start.append(on_request_start)
143-
retry_options = JitterRetry(attempts=attempts, retry_all_server_errors=True)
143+
retry_options = JitterRetry(
144+
attempts=attempts, exceptions={aiohttp.ClientConnectionError}, retry_all_server_errors=True
145+
)
144146
retry_client = RetryClient(retry_options=retry_options, trace_configs=[trace_config])
145147

146148
async with retry_client as session:

tests/test_workers/test_pkg_managers/test_general_js.py

+30
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010
from typing import Any
1111
from unittest import mock
1212

13+
import aiohttp
14+
import aiohttp_retry
1315
import pytest
1416

1517
from cachito.errors import (
1618
FileAccessError,
1719
InvalidFileFormat,
1820
InvalidRepoStructure,
21+
NetworkError,
1922
NexusError,
2023
RepositoryAccessError,
2124
UnsupportedFeature,
@@ -261,6 +264,33 @@ def test_parse_dependency(data):
261264
assert result == (data["p_url"], data["tarball_name"])
262265

263266

267+
@pytest.mark.asyncio
268+
async def test_async_download_binary_file_retries_on_connect_error(tmp_path: Path):
269+
with mock.patch(
270+
"aiohttp.ClientSession._request", side_effect=aiohttp.ClientConnectionError
271+
) as mock_request:
272+
273+
# Make two attempts and retry on ClientConnectionError
274+
retry_options = aiohttp_retry.JitterRetry(
275+
attempts=2,
276+
exceptions={aiohttp.ClientConnectionError},
277+
retry_all_server_errors=True,
278+
)
279+
async with aiohttp_retry.RetryClient(retry_options=retry_options) as retry_client:
280+
281+
# Once the attempts are exhausted, async_download_binary_file raises a NetworkError
282+
with pytest.raises(NetworkError):
283+
_ = await general.async_download_binary_file(
284+
retry_client,
285+
"https://example.com",
286+
tmp_path,
287+
"foo.tgz",
288+
)
289+
290+
# Verify that we made two attempts to download the file
291+
assert mock_request.call_count == 2
292+
293+
264294
@mock.patch("cachito.workers.pkg_managers.general_js.async_download_binary_file")
265295
@pytest.mark.asyncio
266296
async def test_get_dependecies(mock_async_download_binary_file):

0 commit comments

Comments
 (0)