func (c *Config) New(optionalCtx ...context.Context) Backoff {
	ctx := context.Background()
	if len(optionalCtx) > 1 {
		panic("Only up to one optional context must be provided")
	}
	if len(optionalCtx) > 0 {
		ctx = optionalCtx[0]
	}
	ctx, cancel := context.WithCancel(ctx)
	reset := make(chan struct{})
	e := &expBackoff{
		cfg:    c,
		cancel: cancel,
		ctx:    ctx,
		reset:  reset,
	}
	e.c = e.run()
	return e
}
creates new backoff with optional Context
package backoff
import (
	"context"
	"fmt"
	"math"
	"math/rand"
	"time"
)
type (
	Opt func(c *Config)
	Provider interface {
		New(ctx ...context.Context) Backoff
	}
	Backoff interface {
		Attempts() <-chan int
		Close()
		Reset()
	}
	expBackoff struct {
		cfg    *Config
		c      <-chan int
		reset  chan struct{}
		ctx    context.Context
		cancel context.CancelFunc
	}
	Config struct {
		rnd               RandFunc
		maxAttempts       int
		minWait           time.Duration
		maxWait           time.Duration
		backoffFactor     float64
		jitterMaxFraction float64  
	}
	RandFunc func() float64
)
func Always() Opt {
	return WithMaxAttempts(math.MaxInt64)
}
func Once() Opt {
	return WithMaxAttempts(1)
}
func WithMaxAttempts(attempts int) Opt {
	if attempts <= 0 {
		panic(fmt.Sprintf("Attempts must be > 0, got %v", attempts))
	}
	return func(c *Config) {
		c.maxAttempts = attempts
	}
}
func WithMinWait(w time.Duration) Opt {
	if w <= 0 {
		panic(fmt.Sprintf("retry minWait must be positive got %v", w))
	}
	return func(c *Config) {
		c.minWait = w
	}
}
func WithMaxWait(w time.Duration) Opt {
	if w <= 0 {
		panic(fmt.Sprintf("retry maxWait must be positive got %v", w))
	}
	return func(c *Config) {
		c.maxWait = w
	}
}
func WithBackoffFactor(f float64) Opt {
	if f < 1.0 {
		panic(fmt.Sprintf("retry backoff factor must be >= 1 - got %v", f))
	}
	return func(c *Config) {
		c.backoffFactor = f
	}
}
func WithRandFunc(f RandFunc) Opt {
	return func(c *Config) {
		c.rnd = f
	}
}
func WithJitterFraction(f float64) Opt {
	if f < 0 || f > 1 {
		panic(fmt.Sprintf("jitter fraction must be between [0,1] - got %v", f))
	}
	return func(c *Config) {
		c.jitterMaxFraction = f
	}
}
func New(opts ...Opt) Provider {
	cfg := &Config{
		rnd:               rand.Float64,
		maxAttempts:       5,
		minWait:           1 * time.Second,
		maxWait:           15 * time.Second,
		backoffFactor:     2,
		jitterMaxFraction: 0.2,
	}
	for _, opt := range opts {
		opt(cfg)
	}
	if cfg.maxWait < cfg.minWait {
		panic(fmt.Sprintf("retry maxWait (%v) < cfg.minWait (%v)", cfg.maxWait, cfg.minWait))
	}
	return cfg
}