-
Notifications
You must be signed in to change notification settings - Fork 61
Expand file tree
/
Copy pathretry.go
More file actions
78 lines (63 loc) · 1.74 KB
/
retry.go
File metadata and controls
78 lines (63 loc) · 1.74 KB
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package retry
import (
"fmt"
"time"
)
// Action ...
type Action func(attempt uint) error
// AbortableAction ...
type AbortableAction func(attempt uint) (error, bool)
// Model ...
type Model struct {
retry uint
waitTime time.Duration
}
// Times ...
func Times(retry uint) *Model {
Model := Model{}
return Model.Times(retry)
}
// Times ...
func (Model *Model) Times(retry uint) *Model {
Model.retry = retry
return Model
}
// Wait ...
func Wait(waitTime time.Duration) *Model {
Model := Model{}
return Model.Wait(waitTime)
}
// Wait ...
func (Model *Model) Wait(waitTime time.Duration) *Model {
Model.waitTime = waitTime
return Model
}
// Try continues executing the supplied action while this action parameter returns an error and the configured
// number of times has not been reached. Otherwise, it stops and returns the last received error.
func (Model Model) Try(action Action) error {
return Model.TryWithAbort(func(attempt uint) (error, bool) {
return action(attempt), false
})
}
// TryWithAbort continues executing the supplied action while this action parameter returns an error, a false bool
// value and the configured number of times has not been reached. Returning a true value from the action aborts the
// retry loop.
//
// Good for retrying actions which can return a mix of retryable and non-retryable failures.
func (Model Model) TryWithAbort(action AbortableAction) error {
if action == nil {
return fmt.Errorf("no action specified")
}
var err error
var shouldAbort bool
for attempt := uint(0); (0 == attempt || nil != err) && attempt <= Model.retry; attempt++ {
if attempt > 0 && Model.waitTime > 0 {
time.Sleep(Model.waitTime)
}
err, shouldAbort = action(attempt)
if shouldAbort {
break
}
}
return err
}