-
Notifications
You must be signed in to change notification settings - Fork 0
/
retry.go
107 lines (84 loc) · 2.55 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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package koinosmq
import "time"
const (
defaultEBInitialTimeout = (time.Second * 1)
defaultEBMaxTimeout = (time.Second * 30)
defaultEBExponent = 2.0
noRetryTimeout = (time.Second * 1)
)
// CheckRetryResult represents describes whether a retry is requested, and how long to timeout first
type CheckRetryResult struct {
DoRetry bool
Timeout time.Duration
}
// RetryPolicy is an enum
type RetryPolicy int
const (
// NoRetry does not retry
NoRetry RetryPolicy = iota
// ExponentialBackoff retires forever, with exponentially increading sleep
ExponentialBackoff
)
type retryPolicyInterface interface {
SetOptions(interface{})
CheckRetry() *CheckRetryResult
PollTimeout() time.Duration
}
func getRetryPolicy(policy RetryPolicy, options ...interface{}) retryPolicyInterface {
var rp retryPolicyInterface
switch policy {
case NoRetry:
rp = &noRetryPolicy{}
case ExponentialBackoff:
rp = &exponentialBackoffRetryPolicy{
options: ExponentialBackoffOptions{
MaxTimeout: defaultEBMaxTimeout,
Exponent: defaultEBExponent,
NextTimeout: defaultEBInitialTimeout,
},
}
default:
panic("Requested non-existent retry policy")
}
if len(options) > 0 {
rp.SetOptions(options[0])
}
return rp
}
// ----------------------------------------------------------------------------
// RetryPolicy Implementations
// ----------------------------------------------------------------------------
type noRetryPolicy struct {
}
func (rp *noRetryPolicy) SetOptions(interface{}) {}
func (rp *noRetryPolicy) CheckRetry() *CheckRetryResult {
return &CheckRetryResult{DoRetry: false}
}
func (rp *noRetryPolicy) PollTimeout() time.Duration {
return noRetryTimeout
}
// ExponentialBackoffOptions are the options for the exponential backoff policy
type ExponentialBackoffOptions struct {
MaxTimeout time.Duration
Exponent float32
NextTimeout time.Duration
}
type exponentialBackoffRetryPolicy struct {
options ExponentialBackoffOptions
}
func (rp *exponentialBackoffRetryPolicy) SetOptions(o interface{}) {
if options, ok := o.(ExponentialBackoffOptions); ok {
rp.options = options
}
}
func (rp *exponentialBackoffRetryPolicy) PollTimeout() time.Duration {
return rp.options.NextTimeout
}
func (rp *exponentialBackoffRetryPolicy) CheckRetry() *CheckRetryResult {
retry := CheckRetryResult{DoRetry: true, Timeout: rp.options.NextTimeout}
rp.options.NextTimeout = rp.options.NextTimeout * time.Duration(rp.options.Exponent)
if rp.options.NextTimeout > rp.options.MaxTimeout {
rp.options.NextTimeout = rp.options.MaxTimeout
}
return &retry
}