From be36733f6f631bd0f31699c026a204cf98146d20 Mon Sep 17 00:00:00 2001 From: Sylvain Baubeau Date: Tue, 18 Feb 2020 18:05:39 +0100 Subject: [PATCH] Add a MaxDelay option This option ensures the delay between 2 retries can not exceed a specified duration --- options.go | 9 +++++++++ retry.go | 3 +++ retry_test.go | 16 +++++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/options.go b/options.go index fdcd0b7..2ee330c 100644 --- a/options.go +++ b/options.go @@ -17,6 +17,7 @@ type DelayTypeFunc func(n uint, config *Config) time.Duration type Config struct { attempts uint delay time.Duration + maxDelay time.Duration maxJitter time.Duration onRetry OnRetryFunc retryIf RetryIfFunc @@ -51,6 +52,14 @@ func Delay(delay time.Duration) Option { } } +// MaxDelay set maximum delay between retry +// does not apply by default +func MaxDelay(maxDelay time.Duration) Option { + return func(c *Config) { + c.maxDelay = maxDelay + } +} + // MaxJitter sets the maximum random Jitter between retries for RandomDelay func MaxJitter(maxJitter time.Duration) Option { return func(c *Config) { diff --git a/retry.go b/retry.go index 4e8e35e..9b0887c 100644 --- a/retry.go +++ b/retry.go @@ -118,6 +118,9 @@ func Do(retryableFunc RetryableFunc, opts ...Option) error { } delayTime := config.delayType(n, config) + if config.maxDelay > 0 && delayTime > config.maxDelay { + delayTime = config.maxDelay + } time.Sleep(delayTime) } else { return nil diff --git a/retry_test.go b/retry_test.go index 1f04361..25faca5 100644 --- a/retry_test.go +++ b/retry_test.go @@ -141,10 +141,24 @@ func TestRandomDelay(t *testing.T) { func() error { return errors.New("test") }, Attempts(3), DelayType(RandomDelay), - MaxJitter(50 * time.Millisecond), + MaxJitter(50*time.Millisecond), ) dur := time.Since(start) assert.Error(t, err) assert.True(t, dur > 2*time.Millisecond, "3 times random retry is longer then 2ms") assert.True(t, dur < 100*time.Millisecond, "3 times random retry is shorter then 100ms") } + +func TestMaxDelay(t *testing.T) { + start := time.Now() + err := Do( + func() error { return errors.New("test") }, + Attempts(5), + Delay(10*time.Millisecond), + MaxDelay(50*time.Millisecond), + ) + dur := time.Since(start) + assert.Error(t, err) + assert.True(t, dur > 170*time.Millisecond, "5 times with maximum delay retry is longer than 70ms") + assert.True(t, dur < 200*time.Millisecond, "5 times with maximum delay retry is shorter than 200ms") +}