blob: cfc163c51566d44dff3448845f713289fdc6e601 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package retry
import (
"time"
)
// Stop indicates that no more retries should be made.
const Stop time.Duration = -1
type Backoff interface {
// Next gets the duration to wait before retrying the operation or |Stop|
// to indicate that no retries should be made.
Next() time.Duration
// Reset resets to initial state.
Reset()
}
// ZeroBackoff is a fixed policy whose back-off time is always zero, meaning
// that the operation is retried immediately without waiting.
type ZeroBackoff struct{}
func (b *ZeroBackoff) Reset() {}
func (b *ZeroBackoff) Next() time.Duration { return 0 }
// ConstantBackoff is a fixed policy that always returns the same backoff delay.
type ConstantBackoff struct {
interval time.Duration
}
func (b *ConstantBackoff) Reset() {}
func (b *ConstantBackoff) Next() time.Duration { return b.interval }
func NewConstantBackoff(d time.Duration) *ConstantBackoff {
return &ConstantBackoff{interval: d}
}
type maxTriesBackoff struct {
backOff Backoff
maxTries uint64
numTries uint64
}
func (b *maxTriesBackoff) Next() time.Duration {
if b.maxTries > 0 {
if b.maxTries <= b.numTries {
return Stop
}
b.numTries++
}
return b.backOff.Next()
}
func (b *maxTriesBackoff) Reset() {
b.numTries = 0
b.backOff.Reset()
}
// WithMaxRetries wraps a back-off which stops after |max| retries.
func WithMaxRetries(b Backoff, max uint64) Backoff {
return &maxTriesBackoff{backOff: b, maxTries: max}
}
type maxDurationBackoff struct {
backOff Backoff
maxDuration time.Duration
startTime time.Time
c clock
}
func (b *maxDurationBackoff) Next() time.Duration {
if b.c.Since(b.startTime) < b.maxDuration {
return b.backOff.Next()
}
return Stop
}
func (b *maxDurationBackoff) Reset() {
b.startTime = b.c.Now()
b.backOff.Reset()
}
// WithMaxDuration wraps a back-off which stops attempting retries after |max|
// duration.
func WithMaxDuration(b Backoff, max time.Duration) Backoff {
return &maxDurationBackoff{backOff: b, maxDuration: max, c: &systemClock{}}
}