diff --git a/graphql/cache.go b/graphql/cache.go index 24294f72d7f..fe86ca35028 100644 --- a/graphql/cache.go +++ b/graphql/cache.go @@ -1,27 +1,29 @@ package graphql +import "context" + // Cache is a shared store for APQ and query AST caching type Cache interface { // Get looks up a key's value from the cache. - Get(key string) (value interface{}, ok bool) + Get(ctx context.Context, key string) (value interface{}, ok bool) // Add adds a value to the cache. - Add(key string, value interface{}) + Add(ctx context.Context, key string, value interface{}) } // MapCache is the simplest implementation of a cache, because it can not evict it should only be used in tests type MapCache map[string]interface{} // Get looks up a key's value from the cache. -func (m MapCache) Get(key string) (value interface{}, ok bool) { +func (m MapCache) Get(ctx context.Context, key string) (value interface{}, ok bool) { v, ok := m[key] return v, ok } // Add adds a value to the cache. -func (m MapCache) Add(key string, value interface{}) { m[key] = value } +func (m MapCache) Add(ctx context.Context, key string, value interface{}) { m[key] = value } type NoCache struct{} -func (n NoCache) Get(key string) (value interface{}, ok bool) { return nil, false } -func (n NoCache) Add(key string, value interface{}) {} +func (n NoCache) Get(ctx context.Context, key string) (value interface{}, ok bool) { return nil, false } +func (n NoCache) Add(ctx context.Context, key string, value interface{}) {} diff --git a/graphql/handler/executor.go b/graphql/handler/executor.go index b2f69593282..eac1537a5d6 100644 --- a/graphql/handler/executor.go +++ b/graphql/handler/executor.go @@ -185,7 +185,7 @@ func (e executor) DispatchError(ctx context.Context, list gqlerror.List) *graphq func (e executor) parseQuery(ctx context.Context, stats *graphql.Stats, query string) (*ast.QueryDocument, gqlerror.List) { stats.Parsing.Start = graphql.Now() - if doc, ok := e.server.queryCache.Get(query); ok { + if doc, ok := e.server.queryCache.Get(ctx, query); ok { now := graphql.Now() stats.Parsing.End = now @@ -209,7 +209,7 @@ func (e executor) parseQuery(ctx context.Context, stats *graphql.Stats, query st return nil, listErr } - e.server.queryCache.Add(query, doc) + e.server.queryCache.Add(ctx, query, doc) return doc, nil } diff --git a/graphql/handler/extension/apq.go b/graphql/handler/extension/apq.go index 8e4d38d326c..1ea0389fe02 100644 --- a/graphql/handler/extension/apq.go +++ b/graphql/handler/extension/apq.go @@ -72,7 +72,7 @@ func (a AutomaticPersistedQuery) MutateOperationParameters(ctx context.Context, fullQuery := false if rawParams.Query == "" { // client sent optimistic query hash without query string, get it from the cache - query, ok := a.Cache.Get(extension.Sha256) + query, ok := a.Cache.Get(ctx, extension.Sha256) if !ok { err := gqlerror.Errorf(errPersistedQueryNotFound) errcode.Set(err, errPersistedQueryNotFoundCode) @@ -84,7 +84,7 @@ func (a AutomaticPersistedQuery) MutateOperationParameters(ctx context.Context, if computeQueryHash(rawParams.Query) != extension.Sha256 { return gqlerror.Errorf("provided APQ hash does not match query") } - a.Cache.Add(extension.Sha256, rawParams.Query) + a.Cache.Add(ctx, extension.Sha256, rawParams.Query) fullQuery = true } diff --git a/graphql/handler/lru/lru.go b/graphql/handler/lru/lru.go index e539fdf4fe8..e2b1561acbb 100644 --- a/graphql/handler/lru/lru.go +++ b/graphql/handler/lru/lru.go @@ -1,6 +1,8 @@ package lru import ( + "context" + "github.com/99designs/gqlgen/graphql" lru "github.com/hashicorp/golang-lru" ) @@ -21,10 +23,10 @@ func New(size int) *LRU { return &LRU{cache} } -func (l LRU) Get(key string) (value interface{}, ok bool) { +func (l LRU) Get(ctx context.Context, key string) (value interface{}, ok bool) { return l.lru.Get(key) } -func (l LRU) Add(key string, value interface{}) { +func (l LRU) Add(ctx context.Context, key string, value interface{}) { l.lru.Add(key, value) } diff --git a/graphql/handler/server_test.go b/graphql/handler/server_test.go index e141c19e734..630e9a845b7 100644 --- a/graphql/handler/server_test.go +++ b/graphql/handler/server_test.go @@ -93,6 +93,7 @@ func TestServer(t *testing.T) { }) t.Run("query caching", func(t *testing.T) { + ctx := context.Background() cache := &graphql.MapCache{} srv.SetQueryCache(cache) qry := `query Foo {name}` @@ -102,7 +103,7 @@ func TestServer(t *testing.T) { assert.Equal(t, http.StatusOK, resp.Code) assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String()) - cacheDoc, ok := cache.Get(qry) + cacheDoc, ok := cache.Get(ctx, qry) require.True(t, ok) require.Equal(t, "Foo", cacheDoc.(*ast.QueryDocument).Operations[0].Name) }) @@ -110,13 +111,13 @@ func TestServer(t *testing.T) { t.Run("cache hits use document from cache", func(t *testing.T) { doc, err := parser.ParseQuery(&ast.Source{Input: `query Bar {name}`}) require.Nil(t, err) - cache.Add(qry, doc) + cache.Add(ctx, qry, doc) resp := get(srv, "/foo?query="+url.QueryEscape(qry)) assert.Equal(t, http.StatusOK, resp.Code) assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String()) - cacheDoc, ok := cache.Get(qry) + cacheDoc, ok := cache.Get(ctx, qry) require.True(t, ok) require.Equal(t, "Bar", cacheDoc.(*ast.QueryDocument).Operations[0].Name) }) diff --git a/handler/handler.go b/handler/handler.go index c1d2b649ac3..892df53986a 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -226,11 +226,11 @@ type apqAdapter struct { PersistedQueryCache } -func (a apqAdapter) Get(key string) (value interface{}, ok bool) { - return a.PersistedQueryCache.Get(context.Background(), key) +func (a apqAdapter) Get(ctx context.Context, key string) (value interface{}, ok bool) { + return a.PersistedQueryCache.Get(ctx, key) } -func (a apqAdapter) Add(key string, value interface{}) { - a.PersistedQueryCache.Add(context.Background(), key, value.(string)) +func (a apqAdapter) Add(ctx context.Context, key string, value interface{}) { + a.PersistedQueryCache.Add(ctx, key, value.(string)) } type PersistedQueryCache interface {