Skip to content

Commit

Permalink
Add Downloader.DownloadWithAlternates().
Browse files Browse the repository at this point in the history
  • Loading branch information
ericsnowcurrently committed Apr 26, 2016
1 parent aa96c51 commit 7cb027a
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 3 deletions.
15 changes: 12 additions & 3 deletions downloader/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ type Request struct {
TargetDir string

// Verify is used to ensure that the download result is correct. If
// no func is provided then no verification happens.
// the download is invalid then the func must return errors.NotValid.
// If no func is provided then no verification happens.
Verify func(*os.File) error
}

Expand Down Expand Up @@ -113,8 +114,14 @@ func (dl *Download) run(req Request) {

if req.Verify != nil {
err = req.Verify(file)
if _, err2 := file.Seek(0, os.SEEK_SET); err2 != nil && err == nil {
err = err2
if errors.IsNotValid(err) {
logger.Errorf("download from %s invalid: %v", req.URL, err)
}
if _, err2 := file.Seek(0, os.SEEK_SET); err2 != nil {
logger.Errorf("failed to seek to beginning of file: %v", err)
if err == nil {
err = err2
}
} else {
logger.Infof("download verified")
}
Expand All @@ -133,6 +140,8 @@ func (dl *Download) run(req Request) {
}

func download(req Request, openBlob func(*url.URL) (io.ReadCloser, error)) (file *os.File, err error) {
logger.Infof("downloading from %s", req.URL)

dir := req.TargetDir
if dir == "" {
dir = os.TempDir()
Expand Down
29 changes: 29 additions & 0 deletions downloader/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package downloader
import (
"io"
"net/url"
"os"

"github.com/juju/errors"
"github.com/juju/loggo"
Expand Down Expand Up @@ -55,3 +56,31 @@ func (dlr Downloader) Download(req Request, abort <-chan struct{}) (filename str
}
return file.Name(), nil
}

// DownloadWithAlternates tries each of the provided requests until
// one succeeds. If none succeed then the error from the most recent
// attempt is returned. At least one request must be provided.
func (dlr Downloader) DownloadWithAlternates(requests []Request, abort <-chan struct{}) (filename string, err error) {
if len(requests) == 0 {
return "", errors.New("no requests to try")
}

for _, req := range requests {
if err := os.MkdirAll(req.TargetDir, 0755); err != nil {
return "", errors.Trace(err)
}
filename, err = dlr.Download(req, abort)
if errors.IsNotValid(err) {
break
}
if err == nil {
break
}
logger.Errorf("download request to %s failed: %v", req.URL, err)
// Try the next one.
}
if err != nil {
return "", errors.Trace(err)
}
return filename, nil
}

0 comments on commit 7cb027a

Please sign in to comment.