1
0
Fork 0
mirror of synced 2024-06-28 19:20:25 +12:00

Support query batching

This commit is contained in:
Jake Barnby 2022-07-13 15:49:59 +12:00
parent 9e29d5f22d
commit 9909493bfc
3 changed files with 99 additions and 81 deletions

View file

@ -27,9 +27,7 @@ App::get('/v1/graphql')
->label('sdk.response.model', Response::MODEL_ANY)
->label('abuse-limit', 60)
->label('abuse-time', 60)
->param('query', '', new Text(2048), 'The query to execute. Max 2048 chars')
->param('operationName', null, new Text(512), 'Name of the operation to execute. Required if multiple operations are provided', true)
->param('variables', [], new JSON(), 'Map of variables to use as replacement values in the query', true)
->param('query', '', new JSON(), 'The query or queries to execute.', body: true)
->inject('request')
->inject('response')
->inject('utopia')
@ -52,11 +50,7 @@ App::post('/v1/graphql')
->label('sdk.response.model', Response::MODEL_ANY)
->label('abuse-limit', 60)
->label('abuse-time', 60)
->param('query', '', new Text(2048), 'The query to execute. Max 1024 chars. Required if the request content type is "application/json"', true)
->param('operationName', null, new Text(512), 'Name of the operation to execute. Required if multiple operations are provided', true)
->param('variables', [], new JSON(), 'Map of variables to use as replacement values in the query', true)
->param('operations', '', new Text(4096), 'JSON encoded query and variables with nulled file values. Required if the request content type "multipart/form-data"', true)
->param('map', '', new Text(1024), 'Map of form-data filenames to the operations dot-path to inject the file to. For example: "variables.file"', true)
->param('query', '', new JSON(), 'The query or queries to execute.', body: true)
->inject('request')
->inject('response')
->inject('promiseAdapter')
@ -68,11 +62,7 @@ App::post('/v1/graphql')
* @throws \Exception
*/
function graphqlRequest(
string $query,
?string $operationName,
?array $variables,
?string $operations,
?string $map,
array $query,
Appwrite\Utopia\Request $request,
Appwrite\Utopia\Response $response,
CoroutinePromiseAdapter $promiseAdapter,
@ -81,17 +71,23 @@ function graphqlRequest(
$contentType = $request->getHeader('content-type');
if ($contentType === 'application/graphql') {
$query = $request->getSwoole()->rawContent();
$query = [ 'query' => $request->getSwoole()->rawContent() ];
}
$batch = true;
if (!isset($query[0])) {
$batch = false;
$query = [$query];
}
if (\str_starts_with($contentType, 'multipart/form-data')) {
$operations = \json_decode($operations, true);
$map = \json_decode($map, true);
$operations = \json_decode($query[0]['operations'], true);
$map = \json_decode($query[0]['map'], true);
foreach ($map as $fileKey => $locations) {
foreach ($locations as $location) {
$items = &$operations;
foreach (explode('.', $location) as $key) {
if (!isset($items[$key]) || !is_array($items[$key])) {
foreach (\explode('.', $location) as $key) {
if (!isset($items[$key]) || !\is_array($items[$key])) {
$items[$key] = [];
}
$items = &$items[$key];
@ -99,14 +95,14 @@ function graphqlRequest(
$items = $request->getFiles($fileKey);
}
}
$query = $operations['query'];
$variables = $operations['variables'];
$query[0]['query'] = $operations['query'];
$query[0]['variables'] = $operations['variables'];
}
if (empty($query)) {
throw new Exception('No query supplied.', 400, Exception::GRAPHQL_NO_QUERY);
}
$maxComplexity = App::getEnv('_APP_GRAPHQL_MAX_QUERY_COMPLEXITY', 200);
$maxDepth = App::getEnv('_APP_GRAPHQL_MAX_QUERY_DEPTH', 3);
@ -120,22 +116,32 @@ function graphqlRequest(
} else {
$debugFlags = DebugFlag::NONE;
}
$promise = GraphQL::promiseToExecute(
$promiseAdapter,
$gqlSchema,
$query,
variableValues: $variables,
operationName: $operationName,
validationRules: $validations
);
$promises = [];
foreach($query as $indexed) {
$promises[] = GraphQL::promiseToExecute(
$promiseAdapter,
$gqlSchema,
$indexed['query'],
variableValues: $indexed['variables'],
operationName: $indexed['operationName'],
validationRules: $validations
);
}
$output = [];
$wg = new WaitGroup();
$wg->add();
$promise->then(
$promiseAdapter->all($promises)->then(
function ($result) use ($response, &$output, $wg, $debugFlags) {
$output = $result->toArray($debugFlags);
foreach ($result as $queryResponse) {
$output[] = $queryResponse->toArray($debugFlags);
}
if (isset($output[1])) {
$output = \array_merge_recursive(...$output);
} else {
$output = $output[0];
}
$wg->done();
},
function ($error) use ($response, &$output, $wg) {

View file

@ -42,7 +42,7 @@
"ext-sockets": "*",
"appwrite/php-clamav": "1.1.*",
"appwrite/php-runtimes": "0.10.*",
"abnegate/framework": "dev-feat-graphql-helpers",
"utopia-php/framework": "dev-feat-graphql-helpers as 0.19.2",
"utopia-php/logger": "0.3.*",
"utopia-php/abuse": "0.7.*",
"utopia-php/analytics": "0.2.*",
@ -70,17 +70,10 @@
"slickdeals/statsd": "3.1.0",
"webonyx/graphql-php": "14.1.1"
},
"replace": {
"utopia-php/framework": "*"
},
"repositories": [
{
"url": "https://github.com/appwrite/runtimes.git",
"type": "git"
},
{
"url": "https://github.com/abnegate/framework.git",
"type": "git"
}
],
"require-dev": {

101
composer.lock generated
View file

@ -4,46 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "e47b45e70996f8046494cc0db6aeb761",
"content-hash": "b395a62241bc19cb1b7d845e3287808b",
"packages": [
{
"name": "abnegate/framework",
"version": "dev-feat-graphql-helpers",
"source": {
"type": "git",
"url": "https://github.com/abnegate/framework.git",
"reference": "a3bf64536f2d86728a06097717a5cc351d0a88d0"
},
"require": {
"php": ">=8.0.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5.10",
"vimeo/psalm": "4.13.1"
},
"type": "library",
"autoload": {
"psr-4": {
"Utopia\\": "src/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Eldad Fux",
"email": "eldad@appwrite.io"
}
],
"description": "A simple, light and advanced PHP framework",
"keywords": [
"framework",
"php",
"upf"
],
"time": "2022-07-12T00:06:19+00:00"
},
{
"name": "adhocore/jwt",
"version": "1.1.2",
@ -2205,6 +2167,56 @@
},
"time": "2020-02-23T07:40:02+00:00"
},
{
"name": "utopia-php/framework",
"version": "dev-feat-graphql-helpers",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/framework.git",
"reference": "ab785d1605cf1a01cfb9d38f87a15235cdcdf2ca"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/framework/zipball/ab785d1605cf1a01cfb9d38f87a15235cdcdf2ca",
"reference": "ab785d1605cf1a01cfb9d38f87a15235cdcdf2ca",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^9.5.10",
"vimeo/psalm": "4.13.1"
},
"type": "library",
"autoload": {
"psr-4": {
"Utopia\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Eldad Fux",
"email": "eldad@appwrite.io"
}
],
"description": "A simple, light and advanced PHP framework",
"keywords": [
"framework",
"php",
"upf"
],
"support": {
"issues": "https://github.com/utopia-php/framework/issues",
"source": "https://github.com/utopia-php/framework/tree/feat-graphql-helpers"
},
"time": "2022-07-13T03:41:04+00:00"
},
{
"name": "utopia-php/image",
"version": "0.5.4",
@ -5401,10 +5413,17 @@
"time": "2022-05-17T05:48:52+00:00"
}
],
"aliases": [],
"aliases": [
{
"package": "utopia-php/framework",
"version": "dev-feat-graphql-helpers",
"alias": "0.19.2",
"alias_normalized": "0.19.2.0"
}
],
"minimum-stability": "stable",
"stability-flags": {
"abnegate/framework": 20,
"utopia-php/framework": 20,
"utopia-php/registry": 20
},
"prefer-stable": false,