diff --git a/remotes/docker/schema1/converter.go b/remotes/docker/schema1/converter.go index 99940c88a..6e0dcb4e2 100644 --- a/remotes/docker/schema1/converter.go +++ b/remotes/docker/schema1/converter.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "io/ioutil" + "math/rand" "strings" "sync" "time" @@ -215,13 +216,26 @@ func (c *Converter) fetchManifest(ctx context.Context, desc ocispec.Descriptor) func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) error { log.G(ctx).Debug("fetch blob") - ref := remotes.MakeRefKey(ctx, desc) - - calc := newBlobStateCalculator() + var ( + ref = remotes.MakeRefKey(ctx, desc) + calc = newBlobStateCalculator() + retry = 16 + ) +tryit: cw, err := c.contentStore.Writer(ctx, ref, desc.Size, desc.Digest) if err != nil { - if !errdefs.IsAlreadyExists(err) { + if errdefs.IsUnavailable(err) { + select { + case <-time.After(time.Millisecond * time.Duration(rand.Intn(retry))): + if retry < 2048 { + retry = retry << 1 + } + goto tryit + case <-ctx.Done(): + return err + } + } else if !errdefs.IsAlreadyExists(err) { return err } diff --git a/remotes/handlers.go b/remotes/handlers.go index e6d213299..7b1dad99e 100644 --- a/remotes/handlers.go +++ b/remotes/handlers.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "math/rand" "time" "github.com/containerd/containerd/content" @@ -84,7 +85,7 @@ func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc // of writer and abort if not updated recently. select { - case <-time.After(time.Millisecond * time.Duration(retry)): + case <-time.After(time.Millisecond * time.Duration(rand.Intn(retry))): if retry < 2048 { retry = retry << 1 }