func (r *retrierImpl) Reset() {
	r.startTime = r.clock.Now()
	r.currentAttempt = 1
}
Reset will set the Retrier into initial state
package backoff
import (
	"math"
	"math/rand"
	"time"
)
const (
	NoInterval                      = 0
	done              time.Duration = -1
	noMaximumAttempts               = 0
	defaultBackoffCoefficient = 2.0
	defaultMaximumInterval    = 10 * time.Second
	defaultExpirationInterval = time.Minute
	defaultMaximumAttempts    = noMaximumAttempts
	defaultFirstPhaseMaximumAttempts = 3
)
type (
	RetryPolicy interface {
		ComputeNextDelay(elapsedTime time.Duration, numAttempts int) time.Duration
	}
	Retrier interface {
		NextBackOff() time.Duration
		Reset()
	}
	Clock interface {
		Now() time.Time
	}
	ExponentialRetryPolicy struct {
		initialInterval    time.Duration
		backoffCoefficient float64
		maximumInterval    time.Duration
		expirationInterval time.Duration
		maximumAttempts    int
	}
	TwoPhaseRetryPolicy struct {
		firstPolicy  RetryPolicy
		secondPolicy RetryPolicy
	}
	systemClock struct{}
	retrierImpl struct {
		policy         RetryPolicy
		clock          Clock
		currentAttempt int
		startTime      time.Time
	}
)
var SystemClock = systemClock{}
func NewExponentialRetryPolicy(initialInterval time.Duration) *ExponentialRetryPolicy {
	p := &ExponentialRetryPolicy{
		initialInterval:    initialInterval,
		backoffCoefficient: defaultBackoffCoefficient,
		maximumInterval:    defaultMaximumInterval,
		expirationInterval: defaultExpirationInterval,
		maximumAttempts:    defaultMaximumAttempts,
	}
	return p
}
func NewRetrier(policy RetryPolicy, clock Clock) Retrier {
	return &retrierImpl{
		policy:         policy,
		clock:          clock,
		startTime:      clock.Now(),
		currentAttempt: 1,
	}
}
func (p *ExponentialRetryPolicy) SetInitialInterval(initialInterval time.Duration) {
	p.initialInterval = initialInterval
}
func (p *ExponentialRetryPolicy) SetBackoffCoefficient(backoffCoefficient float64) {
	p.backoffCoefficient = backoffCoefficient
}
func (p *ExponentialRetryPolicy) SetMaximumInterval(maximumInterval time.Duration) {
	p.maximumInterval = maximumInterval
}
func (p *ExponentialRetryPolicy) SetExpirationInterval(expirationInterval time.Duration) {
	p.expirationInterval = expirationInterval
}
func (p *ExponentialRetryPolicy) SetMaximumAttempts(maximumAttempts int) {
	p.maximumAttempts = maximumAttempts
}
func (p *ExponentialRetryPolicy) ComputeNextDelay(elapsedTime time.Duration, numAttempts int) time.Duration {
	if p.maximumAttempts != noMaximumAttempts && numAttempts > p.maximumAttempts {
		return done
	}
	if p.expirationInterval != NoInterval && elapsedTime > p.expirationInterval {
		return done
	}
	nextInterval := float64(p.initialInterval) * math.Pow(p.backoffCoefficient, float64(numAttempts-1))
	if nextInterval <= 0 {
		return done
	}
	if p.maximumInterval != NoInterval {
		nextInterval = math.Min(nextInterval, float64(p.maximumInterval))
	}
	if p.expirationInterval != NoInterval {
		remainingTime := float64(math.Max(0, float64(p.expirationInterval-elapsedTime)))
		nextInterval = math.Min(remainingTime, nextInterval)
	}
	nextDuration := time.Duration(nextInterval)
	if nextDuration < p.initialInterval {
		return done
	}
	jitterPortion := int(0.2 * nextInterval)
	if jitterPortion < 1 {
		jitterPortion = 1
	}
	nextInterval = nextInterval*0.8 + float64(rand.Intn(jitterPortion))
	return time.Duration(nextInterval)
}
func (tp *TwoPhaseRetryPolicy) ComputeNextDelay(elapsedTime time.Duration, numAttempts int) time.Duration {
	nextInterval := tp.firstPolicy.ComputeNextDelay(elapsedTime, numAttempts)
	if nextInterval == done {
		nextInterval = tp.secondPolicy.ComputeNextDelay(elapsedTime, numAttempts-defaultFirstPhaseMaximumAttempts)
	}
	return nextInterval
}
func (t systemClock) Now() time.Time {
	return time.Now().UTC()
}