Skip to content

Commit

Permalink
Add backoff utility function
Browse files Browse the repository at this point in the history
  • Loading branch information
airenas committed Dec 23, 2022
1 parent d22bc1b commit b34e3c5
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/airenas/go-app
go 1.18

require (
github.com/cenkalti/backoff/v4 v4.2.0
github.com/rs/zerolog v1.28.0
github.com/spf13/viper v1.14.0
github.com/stretchr/testify v1.8.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
Expand Down
52 changes: 52 additions & 0 deletions pkg/goapp/utils.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package goapp

import (
"context"
"errors"
"fmt"
"io"
"net"
"net/http"
"net/url"
"strings"
"syscall"
"time"

"github.com/cenkalti/backoff/v4"
)

// HidePass removes pass from URL
Expand Down Expand Up @@ -67,3 +73,49 @@ func Sanitize(str string) string {
r := strings.NewReplacer("\n", " ", "\r", " ")
return r.Replace(str)
}

// IsRetryableCode returns true if status is a retryable HTTP code
func IsRetryableCode(c int) bool {
return c != http.StatusBadRequest && c != http.StatusUnauthorized && c != http.StatusNotFound && c != http.StatusConflict
}

// InvokeWithBackoff func with backoff
func InvokeWithBackoff[K any](ctx context.Context, f func() (K, bool, error), b backoff.BackOff) (K, error) {
c := 0
var err error
var res K
var retry bool
op := func() (K, error) {
select {
case <-ctx.Done():
if err != nil {
return res, backoff.Permanent(err)
}
return res, backoff.Permanent(context.DeadlineExceeded)
default:
if c > 0 {
Log.Info().Int("count", c).Msg("retry")
}
}
c++
res, retry, err = f()
if err != nil && !retry {
Log.Info().Msg("not retryable error")
return res, backoff.Permanent(err)
}
return res, err
}
return backoff.RetryWithData(op, b)
}

// IsRetryableErr check if err may be retryable
func IsRetryableErr(err error) bool {
return errors.Is(err, io.EOF) || errors.Is(err, context.DeadlineExceeded) ||
errors.Is(err, syscall.EPIPE) || errors.Is(err, syscall.ECONNRESET) ||
isTimeout(err)
}

func isTimeout(err error) bool {
e, ok := err.(net.Error)
return ok && e.Timeout()
}

0 comments on commit b34e3c5

Please sign in to comment.