Merge pull request #10086 from hashicorp/dnephin/remove-goroutine-from-retry-run

sdk/retry: a few small debug improvements
This commit is contained in:
Daniel Nephin 2021-04-22 13:05:55 -04:00 committed by GitHub
commit 48b22b5658
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 24 deletions

View File

@ -17,7 +17,6 @@ import (
"fmt" "fmt"
"runtime" "runtime"
"strings" "strings"
"sync"
"time" "time"
) )
@ -38,9 +37,13 @@ type R struct {
output []string output []string
} }
func (r *R) Helper() {}
var runFailed = struct{}{}
func (r *R) FailNow() { func (r *R) FailNow() {
r.fail = true r.fail = true
runtime.Goexit() panic(runFailed)
} }
func (r *R) Fatal(args ...interface{}) { func (r *R) Fatal(args ...interface{}) {
@ -93,6 +96,7 @@ func Run(t Failer, f func(r *R)) {
} }
func RunWith(r Retryer, t Failer, f func(r *R)) { func RunWith(r Retryer, t Failer, f func(r *R)) {
t.Helper()
run(r, t, f) run(r, t, f)
} }
@ -100,22 +104,21 @@ func dedup(a []string) string {
if len(a) == 0 { if len(a) == 0 {
return "" return ""
} }
m := map[string]int{} seen := map[string]struct{}{}
for _, s := range a {
m[s] = m[s] + 1
}
var b bytes.Buffer var b bytes.Buffer
for _, s := range a { for _, s := range a {
if _, ok := m[s]; ok { if _, ok := seen[s]; ok {
b.WriteString(s) continue
b.WriteRune('\n')
delete(m, s)
} }
seen[s] = struct{}{}
b.WriteString(s)
b.WriteRune('\n')
} }
return b.String() return b.String()
} }
func run(r Retryer, t Failer, f func(r *R)) { func run(r Retryer, t Failer, f func(r *R)) {
t.Helper()
rr := &R{} rr := &R{}
fail := func() { fail := func() {
t.Helper() t.Helper()
@ -125,19 +128,19 @@ func run(r Retryer, t Failer, f func(r *R)) {
} }
t.FailNow() t.FailNow()
} }
for r.NextOr(fail) { for r.NextOr(t, fail) {
var wg sync.WaitGroup func() {
wg.Add(1) defer func() {
go func() { if p := recover(); p != nil && p != runFailed {
defer wg.Done() panic(p)
}
}()
f(rr) f(rr)
}() }()
wg.Wait() if !rr.fail {
if rr.fail { return
rr.fail = false
continue
} }
break rr.fail = false
} }
} }
@ -161,7 +164,7 @@ func ThreeTimes() *Counter {
type Retryer interface { type Retryer interface {
// NextOr returns true if the operation should be repeated. // NextOr returns true if the operation should be repeated.
// Otherwise, it calls fail and returns false. // Otherwise, it calls fail and returns false.
NextOr(fail func()) bool NextOr(t Failer, fail func()) bool
} }
// Counter repeats an operation a given number of // Counter repeats an operation a given number of
@ -173,7 +176,8 @@ type Counter struct {
count int count int
} }
func (r *Counter) NextOr(fail func()) bool { func (r *Counter) NextOr(t Failer, fail func()) bool {
t.Helper()
if r.count == r.Count { if r.count == r.Count {
fail() fail()
return false return false
@ -196,7 +200,8 @@ type Timer struct {
stop time.Time stop time.Time
} }
func (r *Timer) NextOr(fail func()) bool { func (r *Timer) NextOr(t Failer, fail func()) bool {
t.Helper()
if r.stop.IsZero() { if r.stop.IsZero() {
r.stop = time.Now().Add(r.Timeout) r.stop = time.Now().Add(r.Timeout)
return true return true

View File

@ -22,7 +22,7 @@ func TestRetryer(t *testing.T) {
var iters, fails int var iters, fails int
fail := func() { fails++ } fail := func() { fails++ }
start := time.Now() start := time.Now()
for tt.r.NextOr(fail) { for tt.r.NextOr(t, fail) {
iters++ iters++
} }
dur := time.Since(start) dur := time.Since(start)