Compare commits

...
1 Commits
Author SHA1 Message Date
lukaszraczylo d5655ae2fa Well.. This escalated quickly. 2022-06-08 19:33:34 +01:00
3 changed files with 27 additions and 16 deletions
+13 -3
View File
@@ -23,6 +23,7 @@ import (
"github.com/allegro/bigcache/v3" "github.com/allegro/bigcache/v3"
jsoniter "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
"github.com/lukaszraczylo/go-simple-graphql/pkg/logging" "github.com/lukaszraczylo/go-simple-graphql/pkg/logging"
retry "github.com/sethvargo/go-retry"
"golang.org/x/net/http2" "golang.org/x/net/http2"
) )
@@ -38,7 +39,8 @@ type GraphQL struct {
CacheStore *bigcache.BigCache CacheStore *bigcache.BigCache
RetriesEnable bool RetriesEnable bool
RetriesNumber int RetriesNumber int
RetriesDelay int RetriesDelay time.Duration
BackoffSetup retry.Backoff
} }
func pickGraphqlEndpoint() (graphqlEndpoint string) { func pickGraphqlEndpoint() (graphqlEndpoint string) {
@@ -86,7 +88,7 @@ func NewConnection() *GraphQL {
ReadIdleTimeout: 30 * time.Second, ReadIdleTimeout: 30 * time.Second,
DisableCompression: false, DisableCompression: false,
AllowHTTP: true, AllowHTTP: true,
PingTimeout: 10 * time.Second, PingTimeout: 5 * time.Second,
TLSClientConfig: &tls.Config{ TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, InsecureSkipVerify: true,
}, },
@@ -98,6 +100,7 @@ func NewConnection() *GraphQL {
RetriesEnable: false, RetriesEnable: false,
RetriesNumber: 1, RetriesNumber: 1,
RetriesDelay: 250, RetriesDelay: 250,
BackoffSetup: nil,
} }
var err error var err error
retriesEnable, retriesEnableExists := os.LookupEnv("RETRIES_ENABLE") retriesEnable, retriesEnableExists := os.LookupEnv("RETRIES_ENABLE")
@@ -115,9 +118,16 @@ func NewConnection() *GraphQL {
} }
retriesDelay, retriesDelayExists := os.LookupEnv("RETRIES_DELAY") retriesDelay, retriesDelayExists := os.LookupEnv("RETRIES_DELAY")
if retriesDelayExists { if retriesDelayExists {
g.RetriesDelay, err = strconv.Atoi(retriesDelay) retDel, err := strconv.Atoi(retriesDelay)
if err != nil {
panic("Invalid value for RETRIES_DELAY")
}
g.RetriesDelay = time.Duration(retDel) * time.Millisecond
} }
} }
g.BackoffSetup = retry.NewExponential(g.RetriesDelay)
g.BackoffSetup = retry.WithMaxRetries(uint64(g.RetriesNumber), g.BackoffSetup)
return &g return &g
} }
+13 -12
View File
@@ -9,7 +9,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"time"
"github.com/lukaszraczylo/pandati" "github.com/lukaszraczylo/pandati"
retry "github.com/sethvargo/go-retry" retry "github.com/sethvargo/go-retry"
@@ -67,20 +66,22 @@ func (g *GraphQL) Query(queryContent string, queryVariables interface{}, queryHe
} }
httpRequest, err := http.NewRequest("POST", g.Endpoint, bytes.NewBuffer(query)) httpRequest, err := http.NewRequest("POST", g.Endpoint, bytes.NewBuffer(query))
//httpRequest.Header.Add("Content-Type", "application/json") // httpRequest.Header.Set("Content-Type", "application/json")
if err != nil {
g.Log.Error("Unable to create the request", map[string]interface{}{"_error": err.Error()})
return "", err
}
for header, value := range queryHeaders { for header, value := range queryHeaders {
httpRequest.Header.Add(fmt.Sprintf("%v", header), fmt.Sprintf("%v", value)) httpRequest.Header.Add(fmt.Sprintf("%v", header), fmt.Sprintf("%v", value))
} }
var httpResponse *http.Response var httpResponse *http.Response
backoff := retry.NewExponential(time.Duration(g.RetriesDelay)) retry.Do(ctx, g.BackoffSetup, func(ctx context.Context) error {
backoff = retry.WithMaxRetries(uint64(g.RetriesNumber), backoff)
retry.Do(ctx, backoff, func(ctx context.Context) error {
httpResponse, err = g.HttpClient.Do(httpRequest) httpResponse, err = g.HttpClient.Do(httpRequest)
if err != nil { if err != nil {
g.Log.Error("Unable to send the query", map[string]interface{}{"_error": err.Error()}) g.Log.Debug("Unable to send the query RETRY", map[string]interface{}{"_error": err.Error()})
return err return err
} }
if httpResponse.StatusCode <= 200 && httpResponse.StatusCode >= 204 { if httpResponse.StatusCode <= 200 && httpResponse.StatusCode >= 204 {
@@ -92,19 +93,19 @@ func (g *GraphQL) Query(queryContent string, queryVariables interface{}, queryHe
body, err = ioutil.ReadAll(httpResponse.Body) body, err = ioutil.ReadAll(httpResponse.Body)
if err != nil { if err != nil {
g.Log.Critical("Unable to read the response", map[string]interface{}{"_error": err.Error()}) g.Log.Debug("Unable to read the response", map[string]interface{}{"_error": err.Error()})
return retry.RetryableError(errors.New(fmt.Sprintf("body parsing %v", httpResponse.StatusCode))) return retry.RetryableError(errors.New(fmt.Sprintf("RETRY: body parsing %v", httpResponse.StatusCode)))
} }
err = json.Unmarshal(body, &queryResult) err = json.Unmarshal(body, &queryResult)
if err != nil { if err != nil {
g.Log.Error("Unable to unmarshal the query", map[string]interface{}{"_error": err.Error()}) g.Log.Debug("Unable to unmarshal the query", map[string]interface{}{"_error": err.Error()})
return retry.RetryableError(errors.New(fmt.Sprintf("body unmarshal %v", httpResponse.StatusCode))) return retry.RetryableError(errors.New(fmt.Sprintf("RETRY: body unmarshal %v", httpResponse.StatusCode)))
} }
return nil return nil
}) })
if !pandati.IsZero(queryResult.Errors) || err != nil { if !pandati.IsZero(queryResult.Errors) {
g.Log.Error("Query returned error", map[string]interface{}{"_query": queryContent, "_variables": queryVariables, "_error": fmt.Sprintf("%v", queryResult.Errors), "_response_code": httpResponse.StatusCode}) g.Log.Error("Query returned error", map[string]interface{}{"_query": queryContent, "_variables": queryVariables, "_error": fmt.Sprintf("%v", queryResult.Errors), "_response_code": httpResponse.StatusCode})
return "", fmt.Errorf("%v", queryResult.Errors) return "", fmt.Errorf("%v", queryResult.Errors)
} }
+1 -1
View File
@@ -143,7 +143,7 @@ func (suite *TestSuite) Test_GraphQL_Query() {
}, },
{ {
name: "Valid query to https endpoint", name: "Valid query to https endpoint",
endpoint: "https://telegram-bot.app/v1/graphql", endpoint: "https://hasura.local/v1/graphql",
isLocal: false, isLocal: false,
args: args{ args: args{
queryContent: `query packages_prices { queryContent: `query packages_prices {