From 940db1f962c24864fea7e41362f383e163bedd1a Mon Sep 17 00:00:00 2001 From: Andrii Zavorotnii Date: Mon, 14 Jan 2019 10:34:47 -0800 Subject: [PATCH 1/4] Fix cacheSize usage in handler --- handler/graphql.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/handler/graphql.go b/handler/graphql.go index eb8880deb3b..3be36ae6d77 100644 --- a/handler/graphql.go +++ b/handler/graphql.go @@ -259,7 +259,7 @@ func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc var cache *lru.Cache if cfg.cacheSize > 0 { var err error - cache, err = lru.New(DefaultCacheSize) + cache, err = lru.New(cfg.cacheSize) if err != nil { // An error is only returned for non-positive cache size // and we already checked for that. From a76e022803d49a5e4cdc95504766e2060fb7124a Mon Sep 17 00:00:00 2001 From: Andrii Zavorotnii Date: Mon, 14 Jan 2019 10:35:44 -0800 Subject: [PATCH 2/4] Add cache usage for websocket connection --- handler/graphql.go | 2 +- handler/websocket.go | 30 +++++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/handler/graphql.go b/handler/graphql.go index 3be36ae6d77..b27e967a3c9 100644 --- a/handler/graphql.go +++ b/handler/graphql.go @@ -295,7 +295,7 @@ func (gh *graphqlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } if strings.Contains(r.Header.Get("Upgrade"), "websocket") { - connectWs(gh.exec, w, r, gh.cfg) + connectWs(gh.exec, w, r, gh.cfg, gh.cache) return } diff --git a/handler/websocket.go b/handler/websocket.go index dae262bdf3a..c3dc38e0ead 100644 --- a/handler/websocket.go +++ b/handler/websocket.go @@ -11,6 +11,7 @@ import ( "github.com/99designs/gqlgen/graphql" "github.com/gorilla/websocket" + "github.com/hashicorp/golang-lru" "github.com/vektah/gqlparser" "github.com/vektah/gqlparser/ast" "github.com/vektah/gqlparser/gqlerror" @@ -43,11 +44,12 @@ type wsConnection struct { active map[string]context.CancelFunc mu sync.Mutex cfg *Config + cache *lru.Cache initPayload InitPayload } -func connectWs(exec graphql.ExecutableSchema, w http.ResponseWriter, r *http.Request, cfg *Config) { +func connectWs(exec graphql.ExecutableSchema, w http.ResponseWriter, r *http.Request, cfg *Config, cache *lru.Cache) { ws, err := cfg.upgrader.Upgrade(w, r, http.Header{ "Sec-Websocket-Protocol": []string{"graphql-ws"}, }) @@ -63,6 +65,7 @@ func connectWs(exec graphql.ExecutableSchema, w http.ResponseWriter, r *http.Req conn: ws, ctx: r.Context(), cfg: cfg, + cache: cache, } if !conn.init() { @@ -148,10 +151,27 @@ func (c *wsConnection) subscribe(message *operationMessage) bool { return false } - doc, qErr := gqlparser.LoadQuery(c.exec.Schema(), reqParams.Query) - if qErr != nil { - c.sendError(message.ID, qErr...) - return true + var ( + doc *ast.QueryDocument + cacheHit bool + ) + if c.cache != nil { + val, ok := c.cache.Get(reqParams.Query) + if ok { + doc = val.(*ast.QueryDocument) + cacheHit = true + } + } + if !cacheHit { + var qErr gqlerror.List + doc, qErr = gqlparser.LoadQuery(c.exec.Schema(), reqParams.Query) + if qErr != nil { + c.sendError(message.ID, qErr...) + return true + } + if c.cache != nil { + c.cache.Add(reqParams.Query, doc) + } } op := doc.Operations.ForName(reqParams.OperationName) From 10f4ccde2a5fd79d8cd0fd66d79ceed19dbcd2de Mon Sep 17 00:00:00 2001 From: Andrii Zavorotnii Date: Mon, 14 Jan 2019 10:37:59 -0800 Subject: [PATCH 3/4] newRequestContext: remove redundant else part --- handler/graphql.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/handler/graphql.go b/handler/graphql.go index b27e967a3c9..918671a9a22 100644 --- a/handler/graphql.go +++ b/handler/graphql.go @@ -58,8 +58,6 @@ func (c *Config) newRequestContext(es graphql.ExecutableSchema, doc *ast.QueryDo if hook := c.tracer; hook != nil { reqCtx.Tracer = hook - } else { - reqCtx.Tracer = &graphql.NopTracer{} } if c.complexityLimit > 0 { From 21769d937f1d0f96d31e95d1adcd0f17da13b009 Mon Sep 17 00:00:00 2001 From: Andrii Zavorotnii Date: Mon, 14 Jan 2019 11:47:04 -0800 Subject: [PATCH 4/4] Ensure no side affect from preceding tests in wont_leak_goroutines test --- codegen/testserver/generated_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/codegen/testserver/generated_test.go b/codegen/testserver/generated_test.go index 704869a0813..9ec692b4d6d 100644 --- a/codegen/testserver/generated_test.go +++ b/codegen/testserver/generated_test.go @@ -125,6 +125,7 @@ func TestGeneratedServer(t *testing.T) { t.Run("subscriptions", func(t *testing.T) { t.Run("wont leak goroutines", func(t *testing.T) { + runtime.GC() // ensure no go-routines left from preceding tests initialGoroutineCount := runtime.NumGoroutine() sub := c.Websocket(`subscription { updated }`)