func (b *Backoff) Retry(ctx context.Context, f func() error, retry ...codes.Code) error {
	if ctx.Err() != nil {
		return ctx.Err()
	}
	for {
		if err := f(); !IsRetryable(err, retry...) {
			return err
		}
		select {
		case <-time.After(b.Duration()):
		case <-ctx.Done():
			return ctx.Err()
		}
	}
}
Retry calls a function until it succeeds or the context is done.
It will backoff if the function returns a retryable error.
Once the context is done, retries will end and the most recent error will be returned.
Backoff is not reset by this function.
package backoff
import (
	"context"
	"fmt"
	"math/rand"
	"time"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)
type RetriableError string
func (re RetriableError) Error() string {
	return string(re)
}
func RetriableErrorf(format string, a ...interface{}) error {
	return RetriableError(fmt.Sprintf(format, a...))
}
type Backoff struct {
	Min    time.Duration  
	Max    time.Duration  
	Factor float64        
	Jitter bool           
	delta time.Duration  
}
func (b *Backoff) Duration() time.Duration {
	base := b.Min + b.delta
	pause := base
	if b.Jitter {  
		pause += time.Duration(rand.Int63n(int64(pause)))
	}
	nextPause := time.Duration(float64(base) * b.Factor)
	if nextPause > b.Max || nextPause < b.Min {  
		nextPause = b.Max
	}
	b.delta = nextPause - b.Min
	return pause
}
func (b *Backoff) Reset() {
	b.delta = 0
}