core icon indicating copy to clipboard operation
core copied to clipboard

[GraphQL] Batch requests in Apollo format

Open mahmoodbazdar opened this issue 5 years ago • 4 comments

Description
This Apollo extension allow us to send multiple request at the same time: https://www.apollographql.com/docs/link/links/batch-http/ It will be a good feature to have since we don't support sub class mutation( because of Input union spec) and it force client to send several requests for one action.I think this plugin solve some part of performance issue. Here is Apollo client Article: https://blog.apollographql.com/query-batching-in-apollo-63acfd859862

This plugin changes the requests to this format:

[
  {
    query: < query 0 >,
    variables: < variables for query 0 >,
  },
  {
    query: < query 1 >,
    variables: < variables for query 1 >,
  },
  {
    query: < query n >
    variables: < variables for query n >,
  }
]

I think we have two option to implement this part:

  • Using StandardServer This is good but we need to rewrite request process and remove the current GraphQl executor and replace it with StandardServer. Because StandardServer don't support the file upload we need to process the requests just like before.

  • Calling executor several times. This is the easiest option for implementation.

I wanted to create a pull request for this, I thought its better to talk about it first.

What do you think?

mahmoodbazdar avatar Nov 20 '19 16:11 mahmoodbazdar

It would be nice to have this feature sure :slightly_smiling_face: We are not using the StandardServer to have more control of the API. So it's definitely the second option.

alanpoulain avatar Nov 20 '19 18:11 alanpoulain

Looks good to me as well 🙂

lukasluecke avatar Nov 25 '19 14:11 lukasluecke

Curious if this was ever revisited?

lcottingham avatar Mar 20 '24 21:03 lcottingham

A very rough tweak to the GraphQL entrypoint action __invoke() method would easily parse and handle batched queries.

$requestContent = $request->query->all();

if (isset($content[0]) && is_array($content[0])) {
    // GQL Response returned as array of execution responses
    $executionResult = [];
    
    // Loop through batched query
    foreach ($content as $singleQuery) {
        
        // Handle each query as a single query
        [$query, $operationName, $variables] = $this->parseRequest($request);
        if (null === $query) {
            throw new BadRequestHttpException('GraphQL query is not valid.');
        }
        
        // should probably be in its own method so its can be called in this loop and on single queries
        try {
            $singleExecutionResult = $this->executor->executeQuery(...); // etc
        } catch (\Exception $exception) {
            $singleExecutionResult = (new ExecutionResult(...)); // etc
        }
        
        // Push new result as array to main result array
        $executionResult[] = $singleExecutionResult->toArray($this->debug);
    }
    
    // Return the array of responses
    return new JsonResponse($executionResult);
    
} else {
    // same process as it is now
}

// Return the array of responses
return new JsonResponse($executionResult);

I don't think query batching is necessary or even supported in graphql playground, so this can simply resolve for only the non-html requests to the gql endpoint.

Seems like a really simple and quick implementation to utilising query batching. Sure, it doesn't save on db executions, but this does save on server overhead by cutting out many multiples of network requests that could be consolidated.

lcottingham avatar Mar 21 '24 10:03 lcottingham