@@ -282,6 +282,10 @@ def run_import(self):
282
282
# Allow for two open file descriptors per download:
283
283
# The temporary download file that the file is streamed to initially, and then
284
284
# the actual destination file that it is moved to.
285
+ # Note that with the possibility of a chunked file download,
286
+ # the true number of file descriptors used may be higher,
287
+ # but this is unlikely to be a problem in practice, and we build in extra tolerance
288
+ # in the fd_safe_executor max worker calculation.
285
289
with fd_safe_executor (fds_per_task = 2 ) as executor :
286
290
self .executor = executor
287
291
batch_size = 100
@@ -392,8 +396,27 @@ def __init__(
392
396
)
393
397
394
398
self .session = requests .Session ()
399
+ # Because we create the executor in the run method, we need to track
400
+ # we need to mount the adapter in the create_file_transfer method
401
+ # so that we can introspect the executor to configure the pool correctly.
402
+ self ._adapter_mounted = False
403
+
404
+ def _mount_adapter (self ):
405
+ if not self ._adapter_mounted :
406
+ # If we are using a ThreadPoolExecutor, then we need to make sure
407
+ # that the requests session has enough connections to handle
408
+ # the number of threads.
409
+ max_workers = self .executor ._max_workers
410
+ adapter = requests .adapters .HTTPAdapter (
411
+ pool_connections = max_workers ,
412
+ pool_maxsize = max_workers ,
413
+ )
414
+ self .session .mount ("http://" , adapter )
415
+ self .session .mount ("https://" , adapter )
416
+ self ._adapter_mounted = True
395
417
396
418
def create_file_transfer (self , f , filename , dest ):
419
+ self ._mount_adapter ()
397
420
url = paths .get_content_storage_remote_url (filename , baseurl = self .baseurl )
398
421
return transfer .FileDownload (
399
422
url ,
0 commit comments