Skip to content

Commit c9336a2

Browse files
committed
Improve handling of download concurrency
Don't save download concurrency defaults in the database. Make it easier for individual plugins to override. closes: #8897 https://pulp.plan.io/issues/8897
1 parent 282b6a5 commit c9336a2

8 files changed

Lines changed: 36 additions & 7 deletions

File tree

CHANGES/8897.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The default ``download_concurrency`` of 10 was found to be too high for many client types, it has been reduced to 8. Additionally, where before ``download_concurrency`` would be set to a default value upon creation, it will now be set NULL (but a default value will still be used).

CHANGES/plugin_api/8897.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added a field ``DEFAULT_DOWNLOAD_CONCURRENCY`` to the Remote base class - plugin writers can override the number of concurrent downloads for each type of remote. The default value is 8.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 2.2.24 on 2021-06-13 03:14
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('core', '0065_merge_20210615_1211'),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name='remote',
15+
name='download_concurrency',
16+
field=models.PositiveIntegerField(null=True),
17+
),
18+
]

pulpcore/app/models/repository.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ class Remote(MasterModel):
256256
ON_DEMAND = "on_demand"
257257
STREAMED = "streamed"
258258

259+
DEFAULT_DOWNLOAD_CONCURRENCY = 8
260+
259261
POLICY_CHOICES = (
260262
(IMMEDIATE, "When syncing, download all metadata and content now."),
261263
(
@@ -288,7 +290,7 @@ class Remote(MasterModel):
288290
proxy_username = models.TextField(null=True)
289291
proxy_password = models.TextField(null=True)
290292

291-
download_concurrency = models.PositiveIntegerField(default=10)
293+
download_concurrency = models.PositiveIntegerField(null=True)
292294
policy = models.TextField(choices=POLICY_CHOICES, default=IMMEDIATE)
293295

294296
total_timeout = models.FloatField(

pulpcore/app/serializers/repository.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,12 @@ class RemoteSerializer(ModelSerializer):
136136
help_text="Timestamp of the most recent update of the remote.", read_only=True
137137
)
138138
download_concurrency = serializers.IntegerField(
139-
help_text="Total number of simultaneous connections.", required=False, min_value=1
139+
help_text=(
140+
"Total number of simultaneous connections. If set to zero (0), "
141+
"then the default value will be used."
142+
),
143+
allow_null=True,
144+
required=False,
140145
)
141146
policy = serializers.ChoiceField(
142147
help_text="The policy to use when downloading content.",

pulpcore/download/factory.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ def __init__(self, remote, downloader_overrides=None):
7474
is the downloader class to be used for that scheme, e.g.
7575
{'https': MyCustomDownloader}. These override the default values.
7676
"""
77+
download_concurrency = remote.download_concurrency or remote.DEFAULT_DOWNLOAD_CONCURRENCY
78+
7779
self._remote = remote
7880
self._download_class_map = copy.copy(PROTOCOL_MAP)
7981
if downloader_overrides:
@@ -85,7 +87,7 @@ def __init__(self, remote, downloader_overrides=None):
8587
"file": self._generic,
8688
}
8789
self._session = self._make_aiohttp_session_from_remote()
88-
self._semaphore = asyncio.Semaphore(value=remote.download_concurrency)
90+
self._semaphore = asyncio.Semaphore(value=download_concurrency)
8991
atexit.register(self._session_cleanup)
9092

9193
def _session_cleanup(self):

pulpcore/download/http.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,9 @@ async def _run(self, extra_data=None):
201201
"""
202202
Download, validate, and compute digests on the `url`. This is a coroutine.
203203
204-
This method is decorated with a backoff-and-retry behavior to retry HTTP 429 and
205-
some 5XX errors. It retries with exponential backoff 10 times before allowing
206-
a final exception to be raised.
204+
This method is decorated with a backoff-and-retry behavior to retry some errors.
205+
It retries with exponential backoff 10 times before allowing a final exception to
206+
be raised.
207207
208208
This method provides the same return object type and documented in
209209
:meth:`~pulpcore.plugin.download.BaseDownloader._run`.

pulpcore/tests/functional/api/using_plugin/test_crud_repos.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ def test_read(self):
254254
self._compare_results(self.remote_attrs, self.remote)
255255

256256
def test_update(self):
257-
data = {"download_concurrency": 66, "policy": "immediate"}
257+
data = {"download_concurrency": 23, "policy": "immediate"}
258258
self.remotes_api.partial_update(self.remote.pulp_href, data)
259259
time.sleep(1) # without this, the read returns the pre-patch values
260260
new_remote = self.remotes_api.read(self.remote.pulp_href)

0 commit comments

Comments
 (0)