func WithRetries()

in pkg/download/retry.go [35:78]


func WithRetries(ctx *log.Context, downloaders []Downloader, sf SleepFunc) (io.ReadCloser, error) {
	var downloadErrors error
	for _, d := range downloaders {
		for n := 0; n < expRetryN; n++ {
			ctx := ctx.With("retry", n)
			status, out, err := Download(ctx, d)
			if err == nil {
				return out, nil
			}

			if downloadErrors != nil {
				downloadErrors = errors.Wrapf(downloadErrors, fmt.Sprintf("Attempt %d: %s ", n+1, err.Error()))
			} else {
				downloadErrors = err
			}

			ctx.Log("error", err)

			if out != nil { // we are not going to read this response body
				out.Close()
			}

			// If there is an access issue while downloading using this downloader, use next downloader
			// For ex. User may have set up access to blob using managed identity, but not using public blob access or vice-versa.
			if isAccessIssueHttpStatusCode(status) {
				break
			}

			// status == -1 the value when there was no http request
			if status != -1 && !isTransientHttpStatusCode(status) {
				ctx.Log("info", fmt.Sprintf("downloader %T returned %v, skipping retries", d, status))
				break
			}

			if n != expRetryN-1 {
				// have more retries to go, sleep before retrying
				slp := expRetryK * time.Duration(int(math.Pow(float64(expRetryM), float64(n))))
				ctx.Log("sleep", slp)
				sf(slp)
			}
		}
	}
	return nil, downloadErrors
}