mirror of
https://github.com/lukaszraczylo/go-simple-graphql.git
synced 2026-10-12 00:45:31 +00:00
Revamp the query compilation process.
This commit is contained in:
@@ -2,37 +2,56 @@ package gql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/gookit/goutil"
|
||||
"github.com/gookit/goutil/strutil"
|
||||
)
|
||||
|
||||
var jsonBufferPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new([]byte)
|
||||
},
|
||||
}
|
||||
|
||||
func (b *BaseClient) convertToJSON(v any) []byte {
|
||||
jsonBuffer := jsonBufferPool.Get().(*[]byte)
|
||||
defer jsonBufferPool.Put(jsonBuffer)
|
||||
|
||||
*jsonBuffer = (*jsonBuffer)[:0]
|
||||
jsonData, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
b.Logger.Error("Can't convert to JSON", map[string]interface{}{"error": err.Error()})
|
||||
return nil
|
||||
}
|
||||
return jsonData
|
||||
*jsonBuffer = append(*jsonBuffer, jsonData...)
|
||||
return *jsonBuffer
|
||||
}
|
||||
|
||||
func (b *BaseClient) compileQuery(queryPartials ...any) *Query {
|
||||
q := &Query{}
|
||||
var query string
|
||||
var variables map[string]interface{}
|
||||
for _, partial := range queryPartials {
|
||||
switch val := partial.(type) {
|
||||
case string:
|
||||
q.Query = val
|
||||
query = val
|
||||
case map[string]interface{}:
|
||||
q.Variables = val
|
||||
variables = val
|
||||
}
|
||||
}
|
||||
if q.Query == "" {
|
||||
|
||||
if query == "" {
|
||||
b.Logger.Error("Can't compile query", map[string]interface{}{"error": "query is empty"})
|
||||
return nil
|
||||
}
|
||||
q.JsonQuery = b.convertToJSON(q)
|
||||
return q
|
||||
|
||||
jsonQuery := b.convertToJSON(&Query{Query: query, Variables: variables})
|
||||
return &Query{
|
||||
Query: query,
|
||||
Variables: variables,
|
||||
JsonQuery: jsonQuery,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BaseClient) Query(query string, variables map[string]interface{}, headers map[string]interface{}) (any, error) {
|
||||
@@ -52,8 +71,7 @@ func (b *BaseClient) Query(query string, variables map[string]interface{}, heade
|
||||
if (enableCache || b.cache_global) && strutil.HasPrefix(compiledQuery.Query, "query") {
|
||||
b.Logger.Debug("Cache enabled", nil)
|
||||
queryHash = calculateHash(compiledQuery)
|
||||
cachedValue := b.cacheLookup(queryHash)
|
||||
if cachedValue != nil {
|
||||
if cachedValue := b.cacheLookup(queryHash); cachedValue != nil {
|
||||
b.Logger.Debug("Cache hit", map[string]interface{}{"query": compiledQuery})
|
||||
return cachedValue, nil
|
||||
}
|
||||
@@ -76,7 +94,6 @@ func (b *BaseClient) Query(query string, variables map[string]interface{}, heade
|
||||
}(),
|
||||
Retries: enableRetries || b.retries_enable,
|
||||
}
|
||||
defer func() { q = nil }()
|
||||
|
||||
rv, err := q.executeQuery()
|
||||
if err != nil {
|
||||
@@ -84,8 +101,7 @@ func (b *BaseClient) Query(query string, variables map[string]interface{}, heade
|
||||
return nil, err
|
||||
}
|
||||
|
||||
returnedValue, err := q.decodeResponse(rv)
|
||||
return returnedValue, err
|
||||
return q.decodeResponse(rv)
|
||||
}
|
||||
|
||||
func (q *Query) parseHeadersAndVariables(headers map[string]interface{}) (enableCache, enableRetries, recompileRequired bool) {
|
||||
@@ -97,9 +113,12 @@ func (q *Query) parseHeadersAndVariables(headers map[string]interface{}) (enable
|
||||
varEnableRetries, _ := goutil.ToBool(searchForKeysInMapStringInterface(q.Variables, "gqlretries"))
|
||||
enableCache = enableCache || varEnableCache
|
||||
enableRetries = enableRetries || varEnableRetries
|
||||
delete(q.Variables, "gqlcache")
|
||||
delete(q.Variables, "gqlretries")
|
||||
recompileRequired = true
|
||||
|
||||
if varEnableCache || varEnableRetries {
|
||||
delete(q.Variables, "gqlcache")
|
||||
delete(q.Variables, "gqlretries")
|
||||
recompileRequired = true
|
||||
}
|
||||
}
|
||||
|
||||
return enableCache, enableRetries, recompileRequired
|
||||
|
||||
+62
-3
@@ -1,6 +1,8 @@
|
||||
package gql
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Benchmark_compileQuery(bn *testing.B) {
|
||||
b := NewConnection()
|
||||
@@ -12,12 +14,69 @@ func Benchmark_compileQuery(bn *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_convertToJson(bn *testing.B) {
|
||||
func Benchmark_compileQueryWithVariables(bn *testing.B) {
|
||||
b := NewConnection()
|
||||
variables := map[string]interface{}{
|
||||
"var1": "value1",
|
||||
}
|
||||
bn.ResetTimer()
|
||||
for i := 0; i < bn.N; i++ {
|
||||
b.convertToJSON(
|
||||
b.compileQuery(
|
||||
`query { viewer { login } }`,
|
||||
variables,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_convertToJson(bn *testing.B) {
|
||||
b := NewConnection()
|
||||
query := `query { viewer { login } }`
|
||||
bn.ResetTimer()
|
||||
for i := 0; i < bn.N; i++ {
|
||||
b.convertToJSON(query)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Query(bn *testing.B) {
|
||||
b := NewConnection()
|
||||
query := `query { viewer { login } }`
|
||||
variables := map[string]interface{}{
|
||||
"var1": "value1",
|
||||
}
|
||||
headers := map[string]interface{}{
|
||||
"Authorization": "Bearer token",
|
||||
"gqlcache": "true",
|
||||
}
|
||||
bn.ResetTimer()
|
||||
for i := 0; i < bn.N; i++ {
|
||||
_, _ = b.Query(query, variables, headers)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_QueryNoCacheNoRetry(bn *testing.B) {
|
||||
b := NewConnection()
|
||||
query := `query { viewer { login } }`
|
||||
variables := map[string]interface{}{
|
||||
"var1": "value1",
|
||||
}
|
||||
headers := map[string]interface{}{
|
||||
"Authorization": "Bearer token",
|
||||
}
|
||||
bn.ResetTimer()
|
||||
for i := 0; i < bn.N; i++ {
|
||||
_, _ = b.Query(query, variables, headers)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_QueryWithEmptyVariables(bn *testing.B) {
|
||||
b := NewConnection()
|
||||
query := `query { viewer { login } }`
|
||||
headers := map[string]interface{}{
|
||||
"Authorization": "Bearer token",
|
||||
"gqlcache": "true",
|
||||
}
|
||||
bn.ResetTimer()
|
||||
for i := 0; i < bn.N; i++ {
|
||||
_, _ = b.Query(query, nil, headers)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user