From 786849b2ada27b3e6cccb2164765a157eaf8b983 Mon Sep 17 00:00:00 2001 From: Lucas Costa Date: Thu, 16 May 2019 19:00:12 -0300 Subject: [PATCH] Use Executor for getting responses Use an Executor of the same type as configured to get backend responses.This leverages the batching functionality, allowing batched requests to be processed concurrently. --- graphql_server/__init__.py | 16 ++++++++++++++-- tests/test_query.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/graphql_server/__init__.py b/graphql_server/__init__.py index e7457f7..1facd4d 100644 --- a/graphql_server/__init__.py +++ b/graphql_server/__init__.py @@ -15,7 +15,9 @@ from graphql import get_default_backend from graphql.error import format_error as default_format_error from graphql.execution import ExecutionResult +from graphql.execution.executors.sync import SyncExecutor from graphql.type import GraphQLSchema +from promise import Promise, is_thenable from .error import HttpQueryError @@ -120,10 +122,20 @@ def run_http_query( all_params = [get_graphql_params(entry, extra_data) for entry in data] - results = [ - get_response(schema, params, catch_exc, allow_only_query, **execute_options) + executor = execute_options.get("executor") + response_executor = executor if executor else SyncExecutor() + + response_promises = [ + response_executor.execute( + get_response, schema, params, catch_exc, allow_only_query, **execute_options + ) for params in all_params ] + response_executor.wait_until_finished() + + results = [ + result.get() if is_thenable(result) else result for result in response_promises + ] return ServerResults(results, all_params) diff --git a/tests/test_query.py b/tests/test_query.py index 07c9e57..7a1857e 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -530,3 +530,36 @@ def test_batch_allows_post_with_operation_name(): assert as_dicts(results) == [ {"data": {"test": "Hello World", "shared": "Hello Everyone"}} ] + + +def test_get_reponses_using_executor(): + class TestExecutor(object): + called = False + waited = False + cleaned = False + + def wait_until_finished(self): + TestExecutor.waited = True + + def clean(self): + TestExecutor.cleaned = True + + def execute(self, fn, *args, **kwargs): + TestExecutor.called = True + return fn(*args, **kwargs) + + query = "{test}" + results, params = run_http_query( + schema, + "get", + {}, + dict(query=query), + executor=TestExecutor(), + return_promise=True, + ) + + assert as_dicts(results) == [{"data": {"test": "Hello World"}}] + assert params == [RequestParams(query=query, variables=None, operation_name=None)] + assert TestExecutor.called + assert TestExecutor.waited + assert TestExecutor.cleaned