Skip to content

Commit

Permalink
RetryConfig: Add MaxBackoff option (fixes #938)
Browse files Browse the repository at this point in the history
  • Loading branch information
stefreak committed May 23, 2017
1 parent 5c11196 commit b2ec58c
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 15 deletions.
7 changes: 4 additions & 3 deletions config/consul_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,10 @@ func TestConsulConfig_Finalize(t *testing.T) {
Password: String(""),
},
Retry: &RetryConfig{
Backoff: TimeDuration(DefaultRetryBackoff),
Enabled: Bool(true),
Attempts: Int(DefaultRetryAttempts),
Backoff: TimeDuration(DefaultRetryBackoff),
MaxBackoff: TimeDuration(DefaultRetryMaxBackoff),
Enabled: Bool(true),
Attempts: Int(DefaultRetryAttempts),
},
SSL: &SSLConfig{
CaCert: String(""),
Expand Down
25 changes: 25 additions & 0 deletions config/retry.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ const (
// DefaultRetryBackoff is the default base for the exponential backoff
// algorithm.
DefaultRetryBackoff = 250 * time.Millisecond

// DefaultRetryMaxBackoff is the default maximum of backoff time
DefaultRetryMaxBackoff = 0 * time.Millisecond
)

// RetryFunc is the signature of a function that supports retries.
Expand All @@ -23,12 +26,17 @@ type RetryFunc func(int) (bool, time.Duration)
type RetryConfig struct {
// Attempts is the total number of maximum attempts to retry before letting
// the error fall through.
// 0 means unlimited.
Attempts *int

// Backoff is the base of the exponentialbackoff. This number will be
// multipled by the next power of 2 on each iteration.
Backoff *time.Duration

// MaxBackoff is an upper limit the result of the sleep time between retries
// A MaxBackoff of zero means there is no limit to the exponential growth of the backoff.
MaxBackoff *time.Duration

// Enabled signals if this retry is enabled.
Enabled *bool
}
Expand All @@ -51,6 +59,8 @@ func (c *RetryConfig) Copy() *RetryConfig {

o.Backoff = c.Backoff

o.MaxBackoff = c.MaxBackoff

o.Enabled = c.Enabled

return &o
Expand Down Expand Up @@ -82,6 +92,10 @@ func (c *RetryConfig) Merge(o *RetryConfig) *RetryConfig {
r.Backoff = o.Backoff
}

if o.MaxBackoff != nil {
r.MaxBackoff = o.MaxBackoff
}

if o.Enabled != nil {
r.Enabled = o.Enabled
}
Expand All @@ -103,6 +117,11 @@ func (c *RetryConfig) RetryFunc() RetryFunc {
base := math.Pow(2, float64(retry))
sleep := time.Duration(base) * TimeDurationVal(c.Backoff)

maxSleep := TimeDurationVal(c.MaxBackoff)
if maxSleep > 0 && maxSleep < sleep {
return true, maxSleep
}

return true, sleep
}
}
Expand All @@ -117,6 +136,10 @@ func (c *RetryConfig) Finalize() {
c.Backoff = TimeDuration(DefaultRetryBackoff)
}

if c.MaxBackoff == nil {
c.MaxBackoff = TimeDuration(DefaultRetryMaxBackoff)
}

if c.Enabled == nil {
c.Enabled = Bool(true)
}
Expand All @@ -131,10 +154,12 @@ func (c *RetryConfig) GoString() string {
return fmt.Sprintf("&RetryConfig{"+
"Attempts:%s, "+
"Backoff:%s, "+
"MaxBackoff:%s, "+
"Enabled:%s"+
"}",
IntGoString(c.Attempts),
TimeDurationGoString(c.Backoff),
TimeDurationGoString(c.MaxBackoff),
BoolGoString(c.Enabled),
)
}
42 changes: 39 additions & 3 deletions config/retry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ func TestRetryConfig_Copy(t *testing.T) {
Enabled: Bool(true),
},
},
{
"max_backoff",
&RetryConfig{
Attempts: Int(0),
Backoff: TimeDuration(20 * time.Second),
MaxBackoff: TimeDuration(100 * time.Second),
Enabled: Bool(true),
},
},
}

for i, tc := range cases {
Expand Down Expand Up @@ -120,6 +129,32 @@ func TestRetryConfig_Merge(t *testing.T) {
&RetryConfig{Backoff: TimeDuration(10 * time.Second)},
&RetryConfig{Backoff: TimeDuration(10 * time.Second)},
},

{
"maxbackoff_overrides",
&RetryConfig{MaxBackoff: TimeDuration(10 * time.Second)},
&RetryConfig{MaxBackoff: TimeDuration(20 * time.Second)},
&RetryConfig{MaxBackoff: TimeDuration(20 * time.Second)},
},
{
"maxbackoff_empty_one",
&RetryConfig{MaxBackoff: TimeDuration(10 * time.Second)},
&RetryConfig{},
&RetryConfig{MaxBackoff: TimeDuration(10 * time.Second)},
},
{
"maxbackoff_empty_two",
&RetryConfig{},
&RetryConfig{MaxBackoff: TimeDuration(10 * time.Second)},
&RetryConfig{MaxBackoff: TimeDuration(10 * time.Second)},
},
{
"maxbackoff_same",
&RetryConfig{MaxBackoff: TimeDuration(10 * time.Second)},
&RetryConfig{MaxBackoff: TimeDuration(10 * time.Second)},
&RetryConfig{MaxBackoff: TimeDuration(10 * time.Second)},
},

{
"enabled_overrides",
&RetryConfig{Enabled: Bool(true)},
Expand Down Expand Up @@ -166,9 +201,10 @@ func TestRetryConfig_Finalize(t *testing.T) {
"empty",
&RetryConfig{},
&RetryConfig{
Attempts: Int(DefaultRetryAttempts),
Backoff: TimeDuration(DefaultRetryBackoff),
Enabled: Bool(true),
Attempts: Int(DefaultRetryAttempts),
Backoff: TimeDuration(DefaultRetryBackoff),
MaxBackoff: TimeDuration(DefaultRetryMaxBackoff),
Enabled: Bool(true),
},
},
}
Expand Down
21 changes: 12 additions & 9 deletions config/vault_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,10 @@ func TestVaultConfig_Finalize(t *testing.T) {
Enabled: Bool(false),
RenewToken: Bool(DefaultVaultRenewToken),
Retry: &RetryConfig{
Backoff: TimeDuration(DefaultRetryBackoff),
Enabled: Bool(true),
Attempts: Int(DefaultRetryAttempts),
Backoff: TimeDuration(DefaultRetryBackoff),
MaxBackoff: TimeDuration(DefaultRetryMaxBackoff),
Enabled: Bool(true),
Attempts: Int(DefaultRetryAttempts),
},
SSL: &SSLConfig{
CaCert: String(""),
Expand Down Expand Up @@ -334,9 +335,10 @@ func TestVaultConfig_Finalize(t *testing.T) {
Enabled: Bool(true),
RenewToken: Bool(DefaultVaultRenewToken),
Retry: &RetryConfig{
Backoff: TimeDuration(DefaultRetryBackoff),
Enabled: Bool(true),
Attempts: Int(DefaultRetryAttempts),
Backoff: TimeDuration(DefaultRetryBackoff),
MaxBackoff: TimeDuration(DefaultRetryMaxBackoff),
Enabled: Bool(true),
Attempts: Int(DefaultRetryAttempts),
},
SSL: &SSLConfig{
CaCert: String(""),
Expand Down Expand Up @@ -370,9 +372,10 @@ func TestVaultConfig_Finalize(t *testing.T) {
Enabled: Bool(true),
RenewToken: Bool(DefaultVaultRenewToken),
Retry: &RetryConfig{
Backoff: TimeDuration(DefaultRetryBackoff),
Enabled: Bool(true),
Attempts: Int(DefaultRetryAttempts),
Backoff: TimeDuration(DefaultRetryBackoff),
MaxBackoff: TimeDuration(DefaultRetryMaxBackoff),
Enabled: Bool(true),
Attempts: Int(DefaultRetryAttempts),
},
SSL: &SSLConfig{
CaCert: String(""),
Expand Down

0 comments on commit b2ec58c

Please sign in to comment.