Skip to content

Commit

Permalink
feat: add Set to errs in retry instead of list
Browse files Browse the repository at this point in the history
  • Loading branch information
maxbolgarin committed Dec 9, 2024
1 parent e2ee317 commit 84d8841
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 5 deletions.
13 changes: 9 additions & 4 deletions cliex.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,15 @@ func (c *HTTP) request(ctx context.Context, url string, opts RequestOpts) (*rest
c.log.Error(msg, "error", err, "address", c.cli.BaseURL+url)
}

var errs []error
errs := abstract.NewSet[string]()
for retry := 1; retry < opts.RetryCount; retry++ {
sleepTime := getSleepTime(retry, opts.RetryWaitTime, opts.RetryMaxWaitTime)

select {
case <-ctx.Done():
return nil, fmt.Errorf("request canceled, got errors: %w", errors.Join(errs...))
return nil, fmt.Errorf("request canceled after %d retries, got errors: %s", retry, errors.Join(lang.Convert(errs.Values(), func(err string) error {
return errors.New(err)
})...))

case <-time.After(sleepTime):
}
Expand All @@ -194,14 +196,17 @@ func (c *HTTP) request(ctx context.Context, url string, opts RequestOpts) (*rest
if !opts.NoLogRetryError {
c.log.Warn("failed "+opts.RequestName+"request after retry", "error", err, "n", retry, "address", c.cli.BaseURL+url)
}
errs = append(errs, err)
errs.Add(err.Error())
continue
}

return resp, nil
}

return nil, fmt.Errorf("failed %srequest after retries, got errors: %w", opts.RequestName, errors.Join(errs...))
return nil, fmt.Errorf("failed %srequest after %d retries, got errors: %s", opts.RequestName, opts.RetryCount,
errors.Join(lang.Convert(errs.Values(), func(err string) error {
return errors.New(err)
})...))
}

// Req performs request with method to the BaseURL + URL and returns response
Expand Down
20 changes: 19 additions & 1 deletion cliex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net/http"
"net/http/httptest"
"strconv"
"strings"
"sync/atomic"
"testing"
"time"
Expand Down Expand Up @@ -493,7 +494,10 @@ func TestRetryMechanism(t *testing.T) {
RetryWaitTime: 10 * time.Millisecond,
RetryMaxWaitTime: 50 * time.Millisecond,
})
assert.Error(t, err)
assert.ErrorContains(t, err, "bad request")
assert.False(t, strings.Contains(err.Error(), "retr"))

requestCount = 0

response, err := client.Request(ctx, "/", cliex.RequestOpts{
Method: http.MethodGet,
Expand All @@ -507,6 +511,20 @@ func TestRetryMechanism(t *testing.T) {
assert.Equal(t, http.StatusOK, response.StatusCode())
assert.Equal(t, "success", result.Message)
assert.Equal(t, retryThreshold, requestCount)

requestCount = 0

_, err = client.Request(ctx, "/", cliex.RequestOpts{
Method: http.MethodGet,
Result: &result,
ForceContentType: cliex.MIMETypeJSON,
RetryCount: 20,
RetryWaitTime: 10 * time.Millisecond,
RetryMaxWaitTime: 50 * time.Millisecond,
})
if assert.ErrorContains(t, err, "bad request") {
assert.True(t, strings.Contains(err.Error(), "retr"))
}
}

func TestCircuitBreaker(t *testing.T) {
Expand Down
4 changes: 4 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,19 @@ type Config struct {
// Format "http://localhost:8080/URL" or "https://localhost:8080/URL".
// Default is empty, means you should provide full URL in Request methods.
BaseURL string `yaml:"base_url" json:"base_url" env:"CLIEX_BASE_URL"`

// UserAgent is the User-Agent header that is used for every request.
// Default is "Golang HTTP client".
UserAgent string `yaml:"user_agent" json:"user_agent" env:"CLIEX_USER_AGENT"`

// AuthToken is the Bearer token that is used for every request.
AuthToken string `yaml:"auth_token" json:"auth_token" env:"CLIEX_AUTH_TOKEN"`

// ProxyAddress is the address of the proxy server.
// format "http://localhost:3128".
// If empty, no proxy will be used.
ProxyAddress string `yaml:"proxy_address" json:"proxy_address" env:"CLIEX_PROXY_ADDRESS"`

// RequestTimeout is the timeout for every request in seconds.
// Default is 30 seconds.
RequestTimeout time.Duration `yaml:"request_timeout" json:"request_timeout" env:"CLIEX_REQUEST_TIMEOUT"`
Expand Down

0 comments on commit 84d8841

Please sign in to comment.