From 6ada2d0fe805a053b977bbc152ed84df64f80161 Mon Sep 17 00:00:00 2001 From: Phil Freeman Date: Mon, 30 Dec 2019 10:45:38 -0800 Subject: [PATCH 1/2] Report errors in parallel when batching --- server/src-lib/Hasura/GraphQL/Transport/HTTP.hs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/server/src-lib/Hasura/GraphQL/Transport/HTTP.hs b/server/src-lib/Hasura/GraphQL/Transport/HTTP.hs index 19f1b63a47628..d72b12d4b4fd3 100644 --- a/server/src-lib/Hasura/GraphQL/Transport/HTTP.hs +++ b/server/src-lib/Hasura/GraphQL/Transport/HTTP.hs @@ -55,8 +55,13 @@ runGQBatched reqId userInfo reqHdrs reqs = -- It's unclear what we should do if we receive multiple -- responses with distinct headers, so just do the simplest thing -- in this case, and don't forward any. - let removeHeaders = flip HttpResponse Nothing . encJFromList . map _hrBody - removeHeaders <$> traverse (runGQ reqId userInfo reqHdrs) batch + let removeHeaders = + flip HttpResponse Nothing + . encJFromList + . map (either (encJFromJValue . encodeGQErr False) _hrBody) + try = flip catchError (pure . Left) . fmap Right + fmap removeHeaders $ + traverse (try . runGQ reqId userInfo reqHdrs) batch runHasuraGQ :: ( MonadIO m From 25d883d68d23dcfe2227ec5a09fcd993e5b3026a Mon Sep 17 00:00:00 2001 From: Phil Freeman Date: Mon, 30 Dec 2019 11:58:28 -0800 Subject: [PATCH 2/2] Add some more test cases --- .../select_query_batching_with_mutation.yaml | 42 +++++++++++++++++++ .../select_query_batching_with_one_error.yaml | 26 ++++++++++++ server/tests-py/test_graphql_queries.py | 8 ++++ 3 files changed, 76 insertions(+) create mode 100644 server/tests-py/queries/graphql_query/basic/select_query_batching_with_mutation.yaml create mode 100644 server/tests-py/queries/graphql_query/basic/select_query_batching_with_one_error.yaml diff --git a/server/tests-py/queries/graphql_query/basic/select_query_batching_with_mutation.yaml b/server/tests-py/queries/graphql_query/basic/select_query_batching_with_mutation.yaml new file mode 100644 index 0000000000000..c18cfc68e09ed --- /dev/null +++ b/server/tests-py/queries/graphql_query/basic/select_query_batching_with_mutation.yaml @@ -0,0 +1,42 @@ +description: GraphQL query to test batching with mixed queries and mutations +url: /v1/graphql +status: 200 +response: + - data: + update_user: + affected_rows: 1 + returning: + - id: '2' + - data: + user: + - id: '1' + name: User 1 + - id: '2' + name: Temp User + - data: + update_user: + affected_rows: 1 + returning: + - id: '2' +query: + - query: | + mutation { + update_user(where: {number: {_eq: "123456780"}}, _set: {name: "Temp User"}) { + affected_rows + returning { id } + } + } + - query: | + query { + user { + id + name + } + } + - query: | + mutation { + update_user(where: {number: {_eq: "123456780"}}, _set: {name: "User 2"}) { + affected_rows + returning { id } + } + } diff --git a/server/tests-py/queries/graphql_query/basic/select_query_batching_with_one_error.yaml b/server/tests-py/queries/graphql_query/basic/select_query_batching_with_one_error.yaml new file mode 100644 index 0000000000000..7b956a61cd619 --- /dev/null +++ b/server/tests-py/queries/graphql_query/basic/select_query_batching_with_one_error.yaml @@ -0,0 +1,26 @@ +description: GraphQL query to test error reporting when batching requests +url: /v1/graphql +status: 200 +response: + - errors: + - extensions: + path: $.selectionSet.does_not_exist + code: validation-failed + message: "field \"does_not_exist\" not found in type: 'query_root'" + - data: + author: + - id: 1 + - id: 2 +query: + - query: | + query { + does_not_exist { + id + } + } + - query: | + query { + author { + id + } + } diff --git a/server/tests-py/test_graphql_queries.py b/server/tests-py/test_graphql_queries.py index 9e2df8bdf4924..4300b67261e21 100644 --- a/server/tests-py/test_graphql_queries.py +++ b/server/tests-py/test_graphql_queries.py @@ -64,6 +64,14 @@ def test_select_query_batching(self, hge_ctx, transport): transport = 'http' check_query_f(hge_ctx, self.dir() + "/select_query_batching.yaml", transport) + def test_select_query_batching_with_mutation(self, hge_ctx, transport): + transport = 'http' + check_query_f(hge_ctx, self.dir() + "/select_query_batching_with_mutation.yaml", transport) + + def test_select_query_batching_with_one_error(self, hge_ctx, transport): + transport = 'http' + check_query_f(hge_ctx, self.dir() + "/select_query_batching_with_one_error.yaml", transport) + @classmethod def dir(cls): return 'queries/graphql_query/basic'