func()

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
	}
}