diff --git a/src/Controller/GraphController.php b/src/Controller/GraphController.php index f800637eb..e6ee79f57 100644 --- a/src/Controller/GraphController.php +++ b/src/Controller/GraphController.php @@ -4,6 +4,7 @@ namespace Overblog\GraphQLBundle\Controller; +use GraphQL\Executor\Promise\Promise; use Overblog\GraphQLBundle\Request\BatchParser; use Overblog\GraphQLBundle\Request\Executor; use Overblog\GraphQLBundle\Request\Parser; @@ -53,7 +54,7 @@ public function batchEndpointAction(Request $request, string $schemaName = null) /** * @return JsonResponse|Response */ - private function createResponse(Request $request, ?string $schemaName, bool $batched) + private function createResponse(Request $request, ?string $schemaName, bool $batched, bool $async = false) { if ('OPTIONS' === $request->getMethod()) { $response = new JsonResponse([], 200); @@ -61,7 +62,7 @@ private function createResponse(Request $request, ?string $schemaName, bool $bat if (!in_array($request->getMethod(), ['POST', 'GET'])) { return new JsonResponse('', 405); } - $payload = $this->processQuery($request, $schemaName, $batched); + $payload = $this->processQuery($request, $schemaName, $batched, $async); $response = new JsonResponse($payload, 200); } $this->addCORSHeadersIfNeeded($response, $request); @@ -80,12 +81,12 @@ private function addCORSHeadersIfNeeded(Response $response, Request $request): v } } - private function processQuery(Request $request, ?string $schemaName, bool $batched): array + private function processQuery(Request $request, ?string $schemaName, bool $batched, bool $async = false): array|Promise { if ($batched) { $payload = $this->processBatchQuery($request, $schemaName); } else { - $payload = $this->processNormalQuery($request, $schemaName); + $payload = $this->processNormalQuery($request, $schemaName, $async); } return $payload; @@ -109,10 +110,14 @@ private function processBatchQuery(Request $request, string $schemaName = null): return $payloads; } - private function processNormalQuery(Request $request, string $schemaName = null): array + private function processNormalQuery(Request $request, string $schemaName = null, bool $async = false): array|Promise { $params = $this->requestParser->parse($request); + if ($async) { + return $this->requestExecutor->execute($schemaName, $params); + } + return $this->requestExecutor->execute($schemaName, $params)->toArray(); } } diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 51ed8fe4d..445e25c8f 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -5,6 +5,7 @@ namespace Overblog\GraphQLBundle\Executor; use GraphQL\Executor\ExecutionResult; +use GraphQL\Executor\Promise\Promise; use GraphQL\Executor\Promise\PromiseAdapter; use GraphQL\GraphQL; use GraphQL\Type\Schema; @@ -42,4 +43,18 @@ public function execute( return $promiseAdapter->wait(GraphQL::promiseToExecute(...func_get_args())); } + + public function executeAsync( + PromiseAdapter $promiseAdapter, + Schema $schema, + string $requestString, + $rootValue = null, + $contextValue = null, + $variableValues = null, + $operationName = null, + ?callable $fieldResolver = null, + ?array $validationRules = null + ): Promise { + return GraphQL::promiseToExecute(...func_get_args()); + } } diff --git a/src/Executor/ExecutorInterface.php b/src/Executor/ExecutorInterface.php index 0cd6ec452..3e480d389 100644 --- a/src/Executor/ExecutorInterface.php +++ b/src/Executor/ExecutorInterface.php @@ -6,6 +6,7 @@ use ArrayObject; use GraphQL\Executor\ExecutionResult; +use GraphQL\Executor\Promise\Promise; use GraphQL\Executor\Promise\PromiseAdapter; use GraphQL\Type\Schema; @@ -28,4 +29,24 @@ public function execute( ?callable $fieldResolver = null, ?array $validationRules = null ): ExecutionResult; + + /** + * @param mixed $rootValue + * @param null $contextValue + * @param null $variableValues + * @param string|null $operationName + * @param array|null $validationRules + * @return Promise + */ + public function executeAsync( + PromiseAdapter $promiseAdapter, + Schema $schema, + string $requestString, + $rootValue = null, + $contextValue = null, + $variableValues = null, + $operationName = null, + ?callable $fieldResolver = null, + ?array $validationRules = null + ): Promise; } diff --git a/src/Request/Executor.php b/src/Request/Executor.php index 3cbd21343..ee2e91f4b 100644 --- a/src/Request/Executor.php +++ b/src/Request/Executor.php @@ -7,6 +7,7 @@ use ArrayObject; use Closure; use GraphQL\Executor\ExecutionResult; +use GraphQL\Executor\Promise\Promise; use GraphQL\Executor\Promise\PromiseAdapter; use GraphQL\Type\Schema; use GraphQL\Validator\DocumentValidator; @@ -127,7 +128,7 @@ public function disableIntrospectionQuery(): void /** * @param array|ArrayObject|object|null $rootValue */ - public function execute(?string $schemaName, array $request, $rootValue = null): ExecutionResult + public function execute(?string $schemaName, array $request, $rootValue = null, bool $async = false): ExecutionResult|Promise { $schema = $this->getSchema($schemaName); /** @var string $schemaName */ @@ -145,6 +146,21 @@ public function execute(?string $schemaName, array $request, $rootValue = null): $executorArgumentsEvent->getSchema()->processExtensions(); + if ($async) { + return $this->executor->executeAsync( + $this->promiseAdapter, + $executorArgumentsEvent->getSchema(), + $executorArgumentsEvent->getRequestString(), + $executorArgumentsEvent->getRootValue(), + $executorArgumentsEvent->getContextValue(), + $executorArgumentsEvent->getVariableValue(), + $executorArgumentsEvent->getOperationName(), + $this->defaultFieldResolver + )->then( + fn ($result) => $this->postExecute($result, $executorArgumentsEvent) + ); + } + $result = $this->executor->execute( $this->promiseAdapter, $executorArgumentsEvent->getSchema(),