...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package internal
16
17 import (
18 "context"
19 "fmt"
20 "time"
21
22 gax "github.com/googleapis/gax-go/v2"
23 )
24
25
26
27
28
29
30
31 func Retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error)) error {
32 return retry(ctx, bo, f, gax.Sleep)
33 }
34
35 func retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error),
36 sleep func(context.Context, time.Duration) error) error {
37 var lastErr error
38 for {
39 stop, err := f()
40 if stop {
41 return err
42 }
43
44 if err != nil && err != context.Canceled && err != context.DeadlineExceeded {
45 lastErr = err
46 }
47 p := bo.Pause()
48 if ctxErr := sleep(ctx, p); ctxErr != nil {
49 if lastErr != nil {
50 return wrappedCallErr{ctxErr: ctxErr, wrappedErr: lastErr}
51 }
52 return ctxErr
53 }
54 }
55 }
56
57
58
59 type wrappedCallErr struct {
60 ctxErr error
61 wrappedErr error
62 }
63
64 func (e wrappedCallErr) Error() string {
65 return fmt.Sprintf("retry failed with %v; last error: %v", e.ctxErr, e.wrappedErr)
66 }
67
68 func (e wrappedCallErr) Unwrap() error {
69 return e.wrappedErr
70 }
71
72
73
74 func (e wrappedCallErr) Is(err error) bool {
75 return e.ctxErr == err || e.wrappedErr == err
76 }
77
View as plain text