Skip to content

Commit

Permalink
Add management of the retries via headers.
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaszraczylo committed Apr 10, 2023
1 parent a7b385f commit 21c9119
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 153 deletions.
10 changes: 4 additions & 6 deletions base.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"time"

"github.com/akyoto/cache"
"github.com/lukaszraczylo/go-simple-graphql/utils/concurrency"
"github.com/lukaszraczylo/go-simple-graphql/utils/logger"

"golang.org/x/net/http2"
Expand All @@ -22,11 +21,10 @@ import (
func NewConnection() *BaseClient {

b := &BaseClient{
client: &http.Client{},
concurrencyManager: concurrency.NewPool(-1),
MaxGoRoutines: -1,
LoggingLevel: logger.Warn,
LoggerColorful: true,
client: &http.Client{},
MaxGoRoutines: -1,
LoggingLevel: logger.Warn,
LoggerColorful: true,
}

if b.LoggerWriter == nil {
Expand Down
34 changes: 29 additions & 5 deletions base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,52 @@ import (

func TestNewConnection(t *testing.T) {
tests := []struct {
want *BaseClient
name string
want *BaseClient
cache bool
endpoint string
output string
name string
}{
{
name: "Test NewConnection",
name: "Test NewConnection https",
endpoint: "https://api.github.com/graphql",
output: "string",
cache: true,
want: &BaseClient{
endpoint: "https://api.github.com/graphql",
responseType: "string",
},
},
{
name: "Test NewConnection http",
endpoint: "http://api.github.com/graphql",
output: "mapstring",
cache: false,
want: &BaseClient{
endpoint: "http://api.github.com/graphql",
responseType: "mapstring",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// temporarily set GRAPHQL_ENDPOINT env variable to https://api.github.com/graphql
// and GRAPHQL_OUTPUT to string
current := os.Getenv("GRAPHQL_ENDPOINT")
defer os.Setenv("GRAPHQL_ENDPOINT", current)
os.Setenv("GRAPHQL_ENDPOINT", "https://api.github.com/graphql")

os.Setenv("GRAPHQL_ENDPOINT", tt.endpoint)
got := NewConnection()
got.SetEndpoint(tt.endpoint)
got.SetOutput(tt.output)
if tt.cache {
got.enableCache()
} else {
got.disableCache()
}

assert.Equal(t, tt.want.endpoint, got.endpoint)
assert.Equal(t, tt.want.responseType, got.responseType)
assert.Equal(t, tt.cache, got.cache.enabled)
})
}
}
Expand Down
31 changes: 16 additions & 15 deletions query.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,17 @@ func (c *BaseClient) NewQuery(q ...any) *Query {
func (c *BaseClient) Query(queryContent string, queryVariables interface{}, queryHeaders map[string]interface{}) (any, error) {

compiledQuery := c.NewQuery(queryContent, queryVariables)
parseQueryHeaders, enabledCache, headersModified := c.parseQueryHeaders(queryHeaders)
parseQueryHeaders, enabledCache, headersModified, enabledRetries := compiledQuery.parseQueryHeaders(queryHeaders)

var should_cache bool
var should_cache, retries_enabled bool
var queryHash string

if headersModified {
should_cache = enabledCache
retries_enabled = enabledRetries
} else {
should_cache = c.cache.enabled
retries_enabled = c.retries.enabled
}

// if queryContent does not start with `query` then we don't want to cache it
Expand All @@ -92,12 +94,13 @@ func (c *BaseClient) Query(queryContent string, queryVariables interface{}, quer
}

q := &queryExecutor{
client: c,
query: compiledQuery.compiledQuery,
headers: parseQueryHeaders,
context: context.Background(),
should_cache: should_cache,
hash: queryHash,
client: c,
query: compiledQuery.compiledQuery,
headers: parseQueryHeaders,
context: context.Background(),
should_cache: should_cache,
retries_enabled: retries_enabled,
hash: queryHash,
}

q.execute()
Expand Down Expand Up @@ -126,26 +129,24 @@ func (c *BaseClient) decodeResponse(jsonData []byte) any {
}
}

func (c *BaseClient) parseQueryHeaders(queryHeaders map[string]interface{}) (returnHeaders map[string]interface{}, cache_enabled bool, headers_modified bool) {
func (q *Query) parseQueryHeaders(queryHeaders map[string]interface{}) (returnHeaders map[string]interface{}, cache_enabled bool, headers_modified bool, retries_enabled bool) {
returnHeaders = make(map[string]interface{})
var err error

for k, v := range queryHeaders {
if k == "gqlcache" {
cache_enabled, err = strconv.ParseBool(fmt.Sprintf("%v", v))
if err != nil {
c.Logger.Error(c, "Can't parse gqlcache header", "error", err.Error())
}
if cache_enabled != c.cache.enabled {
headers_modified = true
panic(fmt.Sprintf("Unable to parse gqlcache value %s", err.Error()))
}
headers_modified = true
continue
}
if k == "gqlretries" {
c.retries.enabled, _ = strconv.ParseBool(fmt.Sprintf("%v", v))
retries_enabled, _ = strconv.ParseBool(fmt.Sprintf("%v", v))
continue
}
returnHeaders[k] = v
}
return returnHeaders, cache_enabled, headers_modified
return returnHeaders, cache_enabled, headers_modified, retries_enabled
}
18 changes: 16 additions & 2 deletions query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,20 @@ func TestBaseClient_decodeResponse(t *testing.T) {
},
want: []byte(`{"data":{"hello":"world"}}`),
},
{
name: "Test decodeResponse - mapstring",
fields: fields{
responseType: "mapstring",
},
args: args{
jsonData: []byte(`{"data":{"hello":"world"}}`),
},
want: map[string]interface{}{
"data": map[string]interface{}{
"hello": "world",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -333,8 +347,8 @@ func TestBaseClient_parseQueryHeaders(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := NewConnection()
if gotReturnHeaders, _, _ := c.parseQueryHeaders(tt.args.queryHeaders); !reflect.DeepEqual(gotReturnHeaders, tt.wantReturnHeaders) {
q := &Query{}
if gotReturnHeaders, _, _, _ := q.parseQueryHeaders(tt.args.queryHeaders); !reflect.DeepEqual(gotReturnHeaders, tt.wantReturnHeaders) {
t.Errorf("BaseClient.parseQueryHeaders() = %v, want %v", gotReturnHeaders, tt.wantReturnHeaders)
}
})
Expand Down
12 changes: 11 additions & 1 deletion request.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ func (c *BaseClient) executeQuery(query []byte, headers any) (result any, err er
httpRequest.Header.Add(key, fmt.Sprintf("%s", value))
}

var retries_available = c.retries.max
if !c.retries.enabled {
retries_available = 1
}

var httpResponse *http.Response

err = retry.Do(
Expand Down Expand Up @@ -56,7 +61,7 @@ func (c *BaseClient) executeQuery(query []byte, headers any) (result any, err er
retry.OnRetry(func(n uint, err error) {
c.Logger.Error(c, "Retrying query", "error", err.Error())
}),
retry.Attempts(uint(c.retries.max)),
retry.Attempts(uint(retries_available)),
retry.DelayType(retry.BackOffDelay),
retry.Delay(time.Duration(c.retries.delay)*time.Second),
retry.LastErrorOnly(true),
Expand All @@ -80,6 +85,11 @@ func (q *queryExecutor) execute() {
}
}

if q.retries_enabled {
q.client.Logger.Debug(q.client, "Retries enabled")
q.client.retries.enabled = true
}

response, err := q.client.executeQuery(q.query, q.headers)
if err != nil {
q.client.Logger.Error(q.client, "Error while executing query;", "error", err.Error())
Expand Down
39 changes: 19 additions & 20 deletions structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"net/http"

"github.com/akyoto/cache"
"github.com/lukaszraczylo/go-simple-graphql/utils/concurrency"
"github.com/lukaszraczylo/go-simple-graphql/utils/logger"
)

Expand All @@ -22,18 +21,17 @@ type retriesConfig struct {
}

type BaseClient struct {
Logger Logger
LoggerWriter Writer
client *http.Client
concurrencyManager *concurrency.Pool
endpoint string
responseType string
cache cacheStore
MaxGoRoutines int
LoggingLevel logger.LogLevel
LoggerColorful bool
validate bool
retries retriesConfig
Logger Logger
LoggerWriter Writer
client *http.Client
endpoint string
responseType string
cache cacheStore
MaxGoRoutines int
LoggingLevel logger.LogLevel
LoggerColorful bool
validate bool
retries retriesConfig
}

type Query struct {
Expand All @@ -44,13 +42,14 @@ type Query struct {
}

type queryExecutor struct {
result queryExecutorResult
context context.Context
client *BaseClient
headers map[string]interface{}
hash string
query []byte
should_cache bool
result queryExecutorResult
context context.Context
client *BaseClient
headers map[string]interface{}
hash string
query []byte
should_cache bool
retries_enabled bool
}

type queryExecutorResult struct {
Expand Down
30 changes: 0 additions & 30 deletions utils/concurrency/concurrency.go

This file was deleted.

74 changes: 0 additions & 74 deletions utils/concurrency/concurrency_test.go

This file was deleted.

0 comments on commit 21c9119

Please sign in to comment.