@@ -74,6 +74,8 @@ internal sealed class Registry
74
74
private const string DockerHubRegistry1 = "registry-1.docker.io" ;
75
75
private const string DockerHubRegistry2 = "registry.hub.docker.com" ;
76
76
private static readonly int s_defaultChunkSizeBytes = 1024 * 64 ;
77
+ private const int MaxDownloadRetries = 5 ;
78
+ private const int FixedDownloadDelayInSeconds = 1 ;
77
79
78
80
private readonly ILogger _logger ;
79
81
private readonly IRegistryAPI _registryAPI ;
@@ -401,33 +403,48 @@ public async Task<string> DownloadBlobAsync(string repository, Descriptor descri
401
403
{
402
404
cancellationToken . ThrowIfCancellationRequested ( ) ;
403
405
string localPath = ContentStore . PathForDescriptor ( descriptor ) ;
404
-
406
+
405
407
if ( File . Exists ( localPath ) )
406
408
{
407
409
// Assume file is up to date and just return it
408
410
return localPath ;
409
411
}
410
-
412
+
411
413
string tempTarballPath = ContentStore . GetTempFile ( ) ;
412
-
413
- try
414
+
415
+ int retryCount = 0 ;
416
+ while ( retryCount < MaxDownloadRetries )
414
417
{
415
- // No local copy, so download one
416
- using Stream responseStream = await _registryAPI . Blob . GetStreamAsync ( repository , descriptor . Digest , cancellationToken ) . ConfigureAwait ( false ) ;
417
-
418
- using ( FileStream fs = File . Create ( tempTarballPath ) )
418
+ try
419
419
{
420
- await responseStream . CopyToAsync ( fs , cancellationToken ) . ConfigureAwait ( false ) ;
420
+ // No local copy, so download one
421
+ using Stream responseStream = await _registryAPI . Blob . GetStreamAsync ( repository , descriptor . Digest , cancellationToken ) . ConfigureAwait ( false ) ;
422
+
423
+ using ( FileStream fs = File . Create ( tempTarballPath ) )
424
+ {
425
+ await responseStream . CopyToAsync ( fs , cancellationToken ) . ConfigureAwait ( false ) ;
426
+ }
427
+
428
+ // Break the loop if successful
429
+ break ;
430
+ }
431
+ catch ( Exception ex )
432
+ {
433
+ retryCount ++ ;
434
+ if ( retryCount >= MaxDownloadRetries )
435
+ {
436
+ throw new UnableToDownloadFromRepositoryException ( repository ) ;
437
+ }
438
+
439
+ _logger . LogTrace ( "Download attempt {0}/{1} for repository '{2}' failed. Error: {3}" , retryCount , MaxDownloadRetries , repository , ex . ToString ( ) ) ;
440
+
441
+ // Wait before retrying
442
+ await Task . Delay ( TimeSpan . FromSeconds ( FixedDownloadDelayInSeconds ) , cancellationToken ) . ConfigureAwait ( false ) ;
421
443
}
422
444
}
423
- catch ( Exception )
424
- {
425
- throw new UnableToDownloadFromRepositoryException ( repository ) ;
426
- }
427
- cancellationToken . ThrowIfCancellationRequested ( ) ;
428
-
445
+
429
446
File . Move ( tempTarballPath , localPath , overwrite : true ) ;
430
-
447
+
431
448
return localPath ;
432
449
}
433
450
0 commit comments