in lib/blobrefresh/refresher.go [82:135]
func (r *Refresher) Refresh(namespace string, d core.Digest, hooks ...PostHook) error {
client, err := r.backends.GetClient(namespace)
if err != nil {
return fmt.Errorf("backend manager: %s", err)
}
// Always check whether the blob is actually available and valid before
// returning a potential pending error. This ensures that the majority of
// errors are propogated quickly and syncronously.
info, err := client.Stat(namespace, d.Hex())
if err != nil {
if err == backenderrors.ErrBlobNotFound {
return ErrNotFound
}
return fmt.Errorf("stat: %s", err)
}
size := datasize.ByteSize(info.Size)
if r.config.SizeLimit > 0 && size > r.config.SizeLimit {
return fmt.Errorf("%s blob exceeds size limit of %s", size, r.config.SizeLimit)
}
id := namespace + ":" + d.Hex()
err = r.requests.Start(id, func() error {
start := time.Now()
if err := r.download(client, namespace, d); err != nil {
return err
}
t := time.Since(start)
r.stats.Timer("download_remote_blob").Record(t)
log.With(
"namespace", namespace,
"name", d.Hex(),
"download_time", t).Info("Downloaded remote blob")
if err := r.metaInfoGenerator.Generate(d); err != nil {
return fmt.Errorf("generate metainfo: %s", err)
}
r.stats.Counter("downloads").Inc(1)
for _, h := range hooks {
h.Run(d)
}
return nil
})
switch err {
case dedup.ErrRequestPending:
return ErrPending
case backenderrors.ErrBlobNotFound:
return ErrNotFound
case dedup.ErrWorkersBusy:
return ErrWorkersBusy
default:
return err
}
}