-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy pathretry.go
62 lines (50 loc) · 1.88 KB
/
retry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package util
import (
"fmt"
"time"
"github.com/gruntwork-io/terratest/parallel"
"log"
)
// Run the specified action and wait up to the specified timeout for it to complete. Return the output of the action if
// it completes on time or an error otherwise.
func DoWithTimeout(actionDescription string, timeout time.Duration, action func() (string, error)) (string, error) {
resultChannel := make(chan parallel.TestResult, 1)
go func() {
out, err := action()
resultChannel <- parallel.TestResult{Description: actionDescription, Value: out, Err: err}
}()
select {
case result := <-resultChannel:
return result.Value, result.Err
case <-time.After(timeout):
return "", TimeoutExceeded{Description: actionDescription, Timeout: timeout}
}
}
// Run the specified action. If it returns a value, return that value. If it returns an error, sleep for
// sleepBetweenRetries and try again, up to a maximum of maxRetries retries.
func DoWithRetry(actionDescription string, maxRetries int, sleepBetweenRetries time.Duration, logger *log.Logger, action func() (string, error)) (string, error) {
for i := 0; i < maxRetries; i++ {
output, err := action()
if err == nil {
return output, nil
}
logger.Printf("%s returned an error: %s. Sleeping for %s and will try again.", actionDescription, err.Error(), sleepBetweenRetries)
time.Sleep(sleepBetweenRetries)
}
return "", MaxRetriesExceeded{Description: actionDescription, MaxRetries: maxRetries}
}
// Custom error types
type TimeoutExceeded struct {
Description string
Timeout time.Duration
}
func (err TimeoutExceeded) Error() string {
return fmt.Sprintf("'%s' did not complete before timeout of %s", err.Description, err.Timeout)
}
type MaxRetriesExceeded struct {
Description string
MaxRetries int
}
func (err MaxRetriesExceeded) Error() string {
return fmt.Sprintf("'%s' unsuccessful after %d retries", err.Description, err.MaxRetries)
}