func (b *exponentialPolicy) incrementCurrentInterval() {
	b.currentInterval = time.Duration(float64(b.currentInterval) * b.factor)
}
Increments the current interval by multiplying it with the multiplier.
package backoff
import (
	"errors"
	"time"
)
const Stop time.Duration = -1
func Permanent(err error) error {
	if err == nil {
		panic("no error specified")
	}
	return &permanentError{
		err: err,
	}
}
type Policy interface {
	NextBackOff() time.Duration
	New() Policy
}
func NewBackOff(policy Policy) *BackOff {
	if b, ok := policy.(*BackOff); ok {
		return b
	}
	return &BackOff{Policy: policy}
}
type BackOff struct {
	Policy
}
func (b *BackOff) With(opts ...Option) *BackOff {
	p := b.Policy
	for _, opt := range opts {
		p = opt.apply(p)
	}
	return NewBackOff(p)
}
func Retry(p Policy, f func() error) (err error) {
	p = p.New()
	for {
		if err = f(); err == nil {
			return
		}
		var permanent *permanentError
		if errors.As(err, &permanent) {
			return permanent.Unwrap()
		}
		duration := p.NextBackOff()
		if duration == Stop {
			break
		}
		time.Sleep(duration)
	}
	return err
}
type permanentError struct {
	err error
}
func (e *permanentError) Error() string {
	return e.err.Error()
}
func (e *permanentError) Unwrap() error {
	return e.err
}
type zeroPolicy struct{}
func (zeroPolicy) NextBackOff() time.Duration { return 0 }
func (zeroPolicy) New() Policy                { return zeroPolicy{} }
var zeroBackOffInstance = NewBackOff(zeroPolicy{})
func ZeroBackOff() *BackOff {
	return zeroBackOffInstance
}
type constantPolicy struct {
	Interval time.Duration
}
func ConstantBackOff(d time.Duration) *BackOff {
	return NewBackOff(&constantPolicy{Interval: d})
}
func (b *constantPolicy) NextBackOff() time.Duration { return b.Interval }
func (b *constantPolicy) New() Policy                { return b }
func ExponentialBackOff(initialInterval time.Duration, factor float64) *BackOff {
	p := &exponentialPolicy{
		initialInterval: initialInterval,
		factor:          factor,
		currentInterval: initialInterval,
	}
	return NewBackOff(p)
}
type exponentialPolicy struct {
	initialInterval time.Duration
	factor          float64
	currentInterval time.Duration
}
func (b *exponentialPolicy) NextBackOff() time.Duration {
	defer b.incrementCurrentInterval()
	return b.currentInterval
}
func (b *exponentialPolicy) New() Policy {
	return &exponentialPolicy{
		initialInterval: b.initialInterval,
		factor:          b.factor,
		currentInterval: b.currentInterval,
	}
}