Split sync and async facade methods

This commit is contained in:
Vladimir Razuvaev 2017-08-17 23:50:25 +07:00
parent c04d037fb1
commit d578b8a22f
3 changed files with 79 additions and 62 deletions

View File

@ -134,6 +134,9 @@ class Executor
} }
/** /**
* Executes DocumentNode against given $schema using given $promiseAdapter for deferred resolvers.
* Returns promise which is always fullfilled with instance of ExecutionResult
*
* @param PromiseAdapter $promiseAdapter * @param PromiseAdapter $promiseAdapter
* @param Schema $schema * @param Schema $schema
* @param DocumentNode $ast * @param DocumentNode $ast

View File

@ -2,9 +2,9 @@
namespace GraphQL; namespace GraphQL;
use GraphQL\Error\Error; use GraphQL\Error\Error;
use GraphQL\Error\InvariantViolation;
use GraphQL\Executor\ExecutionResult; use GraphQL\Executor\ExecutionResult;
use GraphQL\Executor\Executor; use GraphQL\Executor\Executor;
use GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter;
use GraphQL\Executor\Promise\Promise; use GraphQL\Executor\Promise\Promise;
use GraphQL\Language\AST\DocumentNode; use GraphQL\Language\AST\DocumentNode;
use GraphQL\Language\Parser; use GraphQL\Language\Parser;
@ -52,25 +52,58 @@ class GraphQL
* @param \GraphQL\Type\Schema $schema * @param \GraphQL\Type\Schema $schema
* @param string|DocumentNode $source * @param string|DocumentNode $source
* @param mixed $rootValue * @param mixed $rootValue
* @param mixed $contextValue * @param mixed $context
* @param array|null $variableValues * @param array|null $variableValues
* @param string|null $operationName * @param string|null $operationName
* @param callable $fieldResolver * @param callable $fieldResolver
* @param array $validationRules * @param array $validationRules
* @param PromiseAdapter $promiseAdapter
* *
* @return ExecutionResult|Promise * @return ExecutionResult
*/ */
public static function executeQuery( public static function executeQuery(
\GraphQL\Type\Schema $schema, \GraphQL\Type\Schema $schema,
$source, $source,
$rootValue = null, $rootValue = null,
$contextValue = null, $context = null,
$variableValues = null, $variableValues = null,
$operationName = null, $operationName = null,
callable $fieldResolver = null, callable $fieldResolver = null,
array $validationRules = null, array $validationRules = null
PromiseAdapter $promiseAdapter = null )
{
$promiseAdapter = new SyncPromiseAdapter();
$promise = self::promiseToExecute($promiseAdapter, $schema, $source, $rootValue, $context,
$variableValues, $operationName, $fieldResolver, $validationRules);
return $promiseAdapter->wait($promise);
}
/**
* Same as executeQuery(), but requires PromiseAdapter and always returns a Promise
*
* @param PromiseAdapter $promiseAdapter
* @param \GraphQL\Type\Schema $schema
* @param string|DocumentNode $source
* @param mixed $rootValue
* @param mixed $context
* @param array|null $variableValues
* @param string|null $operationName
* @param callable $fieldResolver
* @param array $validationRules
*
* @return Promise
*/
public static function promiseToExecute(
PromiseAdapter $promiseAdapter,
\GraphQL\Type\Schema $schema,
$source,
$rootValue = null,
$context = null,
$variableValues = null,
$operationName = null,
callable $fieldResolver = null,
array $validationRules = null
) )
{ {
try { try {
@ -87,21 +120,25 @@ class GraphQL
$validationErrors = DocumentValidator::validate($schema, $documentNode, $validationRules); $validationErrors = DocumentValidator::validate($schema, $documentNode, $validationRules);
if (!empty($validationErrors)) { if (!empty($validationErrors)) {
return new ExecutionResult(null, $validationErrors); return $promiseAdapter->createFulfilled(
new ExecutionResult(null, $validationErrors)
);
} else { } else {
return Executor::execute( return Executor::promiseToExecute(
$promiseAdapter,
$schema, $schema,
$documentNode, $documentNode,
$rootValue, $rootValue,
$contextValue, $context,
$variableValues, $variableValues,
$operationName, $operationName,
$fieldResolver, $fieldResolver
$promiseAdapter
); );
} }
} catch (Error $e) { } catch (Error $e) {
return new ExecutionResult(null, [$e]); return $promiseAdapter->createFulfilled(
new ExecutionResult(null, [$e])
);
} }
} }
@ -114,9 +151,6 @@ class GraphQL
* @param mixed $contextValue * @param mixed $contextValue
* @param array|null $variableValues * @param array|null $variableValues
* @param string|null $operationName * @param string|null $operationName
* @param callable $fieldResolver
* @param array $validationRules
* @param PromiseAdapter $promiseAdapter
* @return Promise|array * @return Promise|array
*/ */
public static function execute( public static function execute(
@ -125,33 +159,27 @@ class GraphQL
$rootValue = null, $rootValue = null,
$contextValue = null, $contextValue = null,
$variableValues = null, $variableValues = null,
$operationName = null, $operationName = null
callable $fieldResolver = null,
array $validationRules = null,
PromiseAdapter $promiseAdapter = null
) )
{ {
$result = self::executeQuery( $result = self::promiseToExecute(
$promiseAdapter = Executor::getPromiseAdapter(),
$schema, $schema,
$source, $source,
$rootValue, $rootValue,
$contextValue, $contextValue,
$variableValues, $variableValues,
$operationName, $operationName
$fieldResolver,
$validationRules,
$promiseAdapter
); );
if ($result instanceof ExecutionResult) { if ($promiseAdapter instanceof SyncPromiseAdapter) {
return $result->toArray(); $result = $promiseAdapter->wait($result)->toArray();
} } else {
if ($result instanceof Promise) { $result = $result->then(function(ExecutionResult $r) {
return $result->then(function(ExecutionResult $executionResult) { return $r->toArray();
return $executionResult->toArray();
}); });
} }
throw new InvariantViolation("Unexpected execution result"); return $result;
} }
/** /**
@ -163,9 +191,6 @@ class GraphQL
* @param mixed $contextValue * @param mixed $contextValue
* @param array|null $variableValues * @param array|null $variableValues
* @param string|null $operationName * @param string|null $operationName
* @param callable $fieldResolver
* @param array $validationRules
* @param PromiseAdapter $promiseAdapter
* *
* @return ExecutionResult|Promise * @return ExecutionResult|Promise
*/ */
@ -175,23 +200,22 @@ class GraphQL
$rootValue = null, $rootValue = null,
$contextValue = null, $contextValue = null,
$variableValues = null, $variableValues = null,
$operationName = null, $operationName = null
callable $fieldResolver = null,
array $validationRules = null,
PromiseAdapter $promiseAdapter = null
) )
{ {
return self::executeQuery( $result = self::promiseToExecute(
$promiseAdapter = Executor::getPromiseAdapter(),
$schema, $schema,
$source, $source,
$rootValue, $rootValue,
$contextValue, $contextValue,
$variableValues, $variableValues,
$operationName, $operationName
$fieldResolver,
$validationRules,
$promiseAdapter
); );
if ($promiseAdapter instanceof SyncPromiseAdapter) {
$result = $promiseAdapter->wait($result);
}
return $result;
} }
/** /**

View File

@ -9,11 +9,11 @@ use GraphQL\Executor\Executor;
use GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter; use GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter;
use GraphQL\Executor\Promise\Promise; use GraphQL\Executor\Promise\Promise;
use GraphQL\Executor\Promise\PromiseAdapter; use GraphQL\Executor\Promise\PromiseAdapter;
use GraphQL\GraphQL;
use GraphQL\Language\AST\DocumentNode; use GraphQL\Language\AST\DocumentNode;
use GraphQL\Language\Parser; use GraphQL\Language\Parser;
use GraphQL\Utils\AST; use GraphQL\Utils\AST;
use GraphQL\Utils\Utils; use GraphQL\Utils\Utils;
use GraphQL\Validator\DocumentValidator;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
@ -109,28 +109,18 @@ class Helper
throw new RequestError("GET supports only query operation"); throw new RequestError("GET supports only query operation");
} }
$validationErrors = DocumentValidator::validate( $result = GraphQL::promiseToExecute(
$promiseAdapter,
$config->getSchema(), $config->getSchema(),
$doc, $doc,
$this->resolveRootValue($config, $op, $doc, $operationType),
$this->resolveContextValue($config, $op, $doc, $operationType),
$op->variables,
$op->operation,
$config->getDefaultFieldResolver(),
$this->resolveValidationRules($config, $op, $doc, $operationType) $this->resolveValidationRules($config, $op, $doc, $operationType)
); );
if (!empty($validationErrors)) {
$result = $promiseAdapter->createFulfilled(
new ExecutionResult(null, $validationErrors)
);
} else {
$result = Executor::promiseToExecute(
$promiseAdapter,
$config->getSchema(),
$doc,
$this->resolveRootValue($config, $op, $doc, $operationType),
$this->resolveContextValue($config, $op, $doc, $operationType),
$op->variables,
$op->operation,
$config->getDefaultFieldResolver()
);
}
} catch (RequestError $e) { } catch (RequestError $e) {
$result = $promiseAdapter->createFulfilled( $result = $promiseAdapter->createFulfilled(
new ExecutionResult(null, [Error::createLocatedError($e)]) new ExecutionResult(null, [Error::createLocatedError($e)])