diff --git a/README.md b/README.md index 4bb1561..ddea6e1 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,9 @@ Therefore, I present you the simple client to which you can copy & paste your gr * `GRAPHQL_CACHE_TTL` - Cache TTL in seconds for SELECT type of queries. Default: `5` * `GRAPHQL_OUTPUT` - Output format. Default: `byte`, available: `byte`, `string` * `LOG_LEVEL` - Logging level. Default: `info` available: `debug`, `info`, `warn`, `error` - +* `GRAPHQL_RETRIES_ENABLE` - Should retries be enabled? Default: `true` +* `GRAPHQL_RETRIES_NUMBER` - Number of retries: Default: `1` +* `GRAPHQL_RETRIES_DELAY` - Delay in retries in milliseconds. Default: `250` ### Cache @@ -106,7 +106,9 @@ func main() { ## Working with results -I'm using an amazing library [tidwall/gjson](https://github.com/tidwall/gjson) to parse the results and extract the information required in further steps and I strongly recommend this approach as the easiest and close to painless, for example: +Currently attempting to switch to the fork of the [`ask` library](https://github.com/lukaszraczylo/ask) + +Before, I used an amazing library [tidwall/gjson](https://github.com/tidwall/gjson) to parse the results and extract the information required in further steps and I strongly recommend this approach as the easiest and close to painless, for example: ```go result := gjson.Get(result, "tbl_user_group_admins.0.is_admin").Bool() diff --git a/base.go b/base.go index a1bb11f..59c4fa8 100644 --- a/base.go +++ b/base.go @@ -40,6 +40,10 @@ func NewConnection() *BaseClient { b.cache.enabled = envutil.GetBool("GRAPHQL_CACHE_ENABLED", true) b.cache.ttl = envutil.GetInt("GRAPHQL_CACHE_TTL", 60) + b.retries.enabled = envutil.GetBool("GRAPHQL_RETRIES_ENABLED", true) + b.retries.max = envutil.GetInt("GRAPHQL_RETRIES_MAX", 1) + b.retries.delay = envutil.GetInt("GRAPHQL_RETRIES_DELAY", 300) + if b.cache.enabled { var err error b.cache.client, err = bigcache.NewBigCache(bigcache.DefaultConfig(time.Duration(b.cache.ttl) * time.Second)) diff --git a/go.mod b/go.mod index 02c61f0..eb17d66 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( ) require ( + github.com/avast/retry-go/v4 v4.3.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/gookit/color v1.5.3 // indirect github.com/kr/pretty v0.3.0 // indirect diff --git a/go.sum b/go.sum index 8193924..0e964a5 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/avast/retry-go/v4 v4.3.3 h1:G56Bp6mU0b5HE1SkaoVjscZjlQb0oy4mezwY/cGH19w= +github.com/avast/retry-go/v4 v4.3.3/go.mod h1:rg6XFaiuFYII0Xu3RDbZQkxCofFwruZKW8oEF1jpWiU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -33,6 +35,7 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= diff --git a/request.go b/request.go index 79c7397..a3a4604 100644 --- a/request.go +++ b/request.go @@ -5,6 +5,8 @@ import ( "fmt" "io/ioutil" "net/http" + + "github.com/avast/retry-go/v4" ) func (c *BaseClient) executeQuery(query []byte, headers any) (result any, err error) { @@ -21,22 +23,35 @@ func (c *BaseClient) executeQuery(query []byte, headers any) (result any, err er var httpResponse *http.Response - httpResponse, err = c.client.Do(httpRequest) - if err != nil { - c.Logger.Error(c, "Error while executing http request;", "error", err.Error()) - return - } - defer httpResponse.Body.Close() - body, err := ioutil.ReadAll(httpResponse.Body) - if err != nil { - c.Logger.Error(c, "Error while reading http response;", "error", err.Error()) - return - } - err = json.Unmarshal(body, &queryResult) - if err != nil { - c.Logger.Error(c, "Error while unmarshalling http response;", "error", err.Error()) - return - } + err = retry.Do( + func() error { + httpResponse, err = c.client.Do(httpRequest) + if err != nil { + c.Logger.Error(c, "Error while executing http request;", "error", err.Error()) + return err + } + defer httpResponse.Body.Close() + + if httpResponse.StatusCode <= 200 && httpResponse.StatusCode >= 204 { + return err + } + + body, err := ioutil.ReadAll(httpResponse.Body) + if err != nil { + c.Logger.Error(c, "Error while reading http response;", "error", err.Error()) + return err + } + + err = json.Unmarshal(body, &queryResult) + if err != nil { + c.Logger.Error(c, "Error while unmarshalling http response;", "error", err.Error()) + return err + } + + return nil + }, + ) + if len(queryResult.Errors) > 0 { return nil, fmt.Errorf("%v", queryResult.Errors) } diff --git a/structs.go b/structs.go index aa8d7e4..0d84bf6 100644 --- a/structs.go +++ b/structs.go @@ -16,6 +16,12 @@ type cacheStore struct { enabled bool } +type retriesConfig struct { + enabled bool + max int + delay int +} + type BaseClient struct { Logger Logger LoggerWriter Writer @@ -28,6 +34,7 @@ type BaseClient struct { LoggingLevel logger.LogLevel LoggerColorful bool validate bool + retries retriesConfig } type Query struct {