Skip to content

Commit 3a86a17

Browse files
dmitshurgopherbot
authored andcommitted
cmd/gorebuild: add basic retries to Get
Gorebuild involves going over the Internet to fetch bytes. Some errors that it might encounter might be temporary, such that if the caller were to try again after waiting a bit, it might just succeed. Instead of trying exactly once before making it something the user has to deal with, be willing to try a few more times with some delays. This is intended to reduce the chance of false positive failures in reports. Also add a hint for where flags fit to usage text, similarly to how it's there in the package comment. For golang/go#57120. Change-Id: I949fdf49f6317b26326c3c55f93fc6e130fa3839 Reviewed-on: https://go-review.googlesource.com/c/build/+/634655 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Russ Cox <rsc@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
1 parent 75a59aa commit 3a86a17

File tree

2 files changed

+41
-17
lines changed

2 files changed

+41
-17
lines changed

cmd/gorebuild/io.go

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"compress/gzip"
1313
"crypto/sha256"
1414
"encoding/json"
15+
"errors"
1516
"fmt"
1617
"hash/crc32"
1718
"io"
@@ -22,6 +23,7 @@ import (
2223
"sort"
2324
"strconv"
2425
"strings"
26+
"time"
2527
)
2628

2729
// SHA256 returns the hexadecimal SHA256 hash of data.
@@ -31,29 +33,51 @@ func SHA256(data []byte) string {
3133
}
3234

3335
// Get returns the content at the named URL.
34-
func Get(log *Log, url string) (data []byte, err error) {
36+
//
37+
// When it encounters what might be a temporary network error,
38+
// it tries fetching multiple times with delays before giving up.
39+
func Get(log *Log, url string) (_ []byte, err error) {
3540
defer func() {
3641
if err != nil && log != nil {
3742
log.Printf("%s", err)
3843
}
3944
}()
4045

41-
resp, err := http.Get(url)
42-
if err != nil {
43-
return nil, err
44-
}
45-
defer resp.Body.Close()
46-
if resp.StatusCode != 200 {
47-
return nil, fmt.Errorf("get %s: %s", url, resp.Status)
48-
}
49-
data, err = io.ReadAll(resp.Body)
50-
if err != nil {
51-
return nil, fmt.Errorf("get %s: %s", url, err)
52-
}
53-
if log != nil {
54-
log.Printf("downloaded %s", url)
46+
// Fetching happens over an unreliable network connection,
47+
// and will fail sometimes. Be willing to try a few times.
48+
const maxTries = 5
49+
var fetchErrors []error
50+
for i := range maxTries {
51+
time.Sleep(time.Duration(i*i) * time.Second)
52+
resp, err := http.Get(url)
53+
if err != nil {
54+
fetchErrors = append(fetchErrors, fmt.Errorf("attempt %d: failed to GET: %v", i+1, err))
55+
continue
56+
}
57+
if resp.StatusCode != 200 {
58+
body, _ := io.ReadAll(io.LimitReader(resp.Body, 4<<10))
59+
resp.Body.Close()
60+
err := fmt.Errorf("non-200 OK status code: %v body: %q", resp.Status, body)
61+
if resp.StatusCode/100 == 5 {
62+
// Consider a 5xx server response to possibly succeed later.
63+
fetchErrors = append(fetchErrors, fmt.Errorf("attempt %d: %v", i+1, err))
64+
continue
65+
}
66+
return nil, fmt.Errorf("get %s: %v", url, err)
67+
}
68+
body, err := io.ReadAll(resp.Body)
69+
resp.Body.Close()
70+
if err != nil {
71+
fetchErrors = append(fetchErrors, fmt.Errorf("attempt %d: failed to read body: %v", i+1, err))
72+
continue
73+
}
74+
if log != nil {
75+
log.Printf("downloaded %s", url)
76+
}
77+
return body, nil
5578
}
56-
return data, nil
79+
// All tries exhausted, give up at this point.
80+
return nil, fmt.Errorf("get %s: %v", url, errors.Join(fetchErrors...))
5781
}
5882

5983
// GerritTarGz returns a .tar.gz file corresponding to the named repo and ref on Go's Gerrit server.

cmd/gorebuild/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ import (
9191
var pFlag = flag.Int("p", 2, "run `n` builds in parallel")
9292

9393
func usage() {
94-
fmt.Fprintf(os.Stderr, "usage: gorebuild [goos-goarch][@version]...\n")
94+
fmt.Fprintf(os.Stderr, "usage: gorebuild [flags] [goos-goarch][@version]...\n")
9595
flag.PrintDefaults()
9696
os.Exit(2)
9797
}

0 commit comments

Comments
 (0)