Skip to content

Commit 1f2d2d3

Browse files
committed
use retryClient
1 parent 3066337 commit 1f2d2d3

4 files changed

Lines changed: 83 additions & 4 deletions

File tree

client/client.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
"reflect"
1515
"regexp"
1616
"strings"
17+
18+
"github.com/hashicorp/go-retryablehttp"
1719
)
1820

1921
var (
@@ -32,11 +34,17 @@ type Service struct {
3234
Client *APIClient
3335
}
3436

37+
func NewRetryAPIClient() *http.Client {
38+
var retryClient = retryablehttp.NewClient()
39+
retryClient.Backoff = customBackoff
40+
return retryClient.StandardClient()
41+
}
42+
3543
// NewAPIClient creates a new API client.
3644
// optionally a custom http.Client to allow for advanced features such as caching.
3745
func NewAPIClient(cfg *Configuration) *APIClient {
3846
if cfg.HTTPClient == nil {
39-
cfg.HTTPClient = http.DefaultClient
47+
cfg.HTTPClient = NewRetryAPIClient()
4048
}
4149

4250
c := new(APIClient)

client/customRetryPolicies.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package client
2+
3+
import (
4+
"net/http"
5+
"regexp"
6+
"strconv"
7+
"time"
8+
9+
"github.com/hashicorp/go-retryablehttp"
10+
)
11+
12+
var (
13+
rateLimitResetHeaders = []string{
14+
"x-organization-rate-limit-reset",
15+
"x-instant-test-rate-limit-reset",
16+
}
17+
resetHeaderPattern = regexp.MustCompile(`^\s*[0-9]+\s*$`)
18+
)
19+
20+
// Custom backoff function
21+
func customBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration {
22+
if resp == nil {
23+
return 0
24+
}
25+
26+
for _, header := range rateLimitResetHeaders {
27+
if resetTimeStr := resp.Header.Get(header); resetTimeStr != "" {
28+
if waitDuration := parseResetHeader(&resetTimeStr); waitDuration != nil {
29+
return *waitDuration
30+
}
31+
32+
// Default backoff if no valid reset time is found
33+
return retryablehttp.DefaultBackoff(min, max, attemptNum, resp)
34+
}
35+
}
36+
37+
// Default case for no rateLimitResetHeaders
38+
return retryablehttp.DefaultBackoff(min, max, attemptNum, resp)
39+
}
40+
41+
// Function to parse the reset header
42+
func parseResetHeader(value *string) *time.Duration {
43+
if value == nil || !resetHeaderPattern.MatchString(*value) {
44+
return nil
45+
}
46+
47+
// Parse the header value to a Unix timestamp
48+
resetTimeUnix, err := strconv.ParseInt(*value, 10, 64)
49+
if err != nil {
50+
return nil
51+
}
52+
53+
// Calculate the duration until the reset time
54+
resetTime := time.Unix(resetTimeUnix, 0)
55+
waitDuration := time.Until(resetTime)
56+
57+
// Return nil if the reset time has already passed
58+
if waitDuration < 0 {
59+
zeroDuration := time.Duration(0)
60+
return &zeroDuration
61+
}
62+
return &waitDuration
63+
}

go.mod

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
module github.com/thousandeyes/thousandeyes-sdk-go/v3
22

3-
go 1.18
3+
go 1.23
4+
5+
toolchain go1.24.8
46

57
require github.com/stretchr/testify v1.7.2
68

79
require (
810
github.com/davecgh/go-spew v1.1.0 // indirect
11+
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
12+
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
913
github.com/pmezard/go-difflib v1.0.0 // indirect
1014
gopkg.in/yaml.v3 v3.0.1 // indirect
11-
)
15+
)

go.sum

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
22
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
4+
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
5+
github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
6+
github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
37
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
48
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
59
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -8,4 +12,4 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F
812
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
913
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1014
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
11-
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
15+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)