Skip to content

Commit

Permalink
clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
spawnia committed Sep 20, 2024
1 parent c7857a7 commit 7df6e21
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 37 deletions.
9 changes: 3 additions & 6 deletions benchmarks/HugeRequestBench.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ private function generateQuery(int $count): string
for ($i = 0; $i < $count; ++$i) {
$query .= '...foo' . $i . PHP_EOL;
}

$query .= '}' . PHP_EOL;
for ($i = 0; $i < $count; ++$i) {
$query .= 'fragment foo' . $i . ' on Query {' . PHP_EOL;
Expand Down Expand Up @@ -70,9 +71,7 @@ public function benchmark1(): void
*/
public function benchmark10(): void
{
if ($this->query === null) {
$this->query = $this->generateQuery(10);
}
$this->query ??= $this->generateQuery(10);
$this->graphQL($this->query);
}

Expand All @@ -89,9 +88,7 @@ public function benchmark10(): void
*/
public function benchmark100(): void
{
if ($this->query === null) {
$this->query = $this->generateQuery(100);
}
$this->query ??= $this->generateQuery(100);
$this->graphQL($this->query);
}
}
18 changes: 13 additions & 5 deletions benchmarks/QueryBench.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ public function setUp(): void
{
parent::setUp();

$routeName = config('lighthouse.route.name');
$configRepository = $this->app->make(ConfigRepository::class);
assert($configRepository instanceof ConfigRepository);

$routeName = $configRepository->get('lighthouse.route.name');
$this->graphQLEndpoint = route($routeName);
}

Expand All @@ -42,11 +45,16 @@ protected function graphQLEndpointUrl(array $routeParams = []): string
public function setPerformanceTuning(array $params): void
{
$this->setUp();

$configRepository = $this->app->make(ConfigRepository::class);
assert($configRepository instanceof ConfigRepository);

if ($params[0]) {
$this->app->make(ConfigRepository::class)->set('lighthouse.field_middleware', []);
$configRepository->set('lighthouse.field_middleware', []);
}
$this->app->make(ConfigRepository::class)->set('lighthouse.query_cache.enable', $params[1]);
$this->app->make(ConfigRepository::class)->set('lighthouse.validation_cache.enable', $params[2]);

$configRepository->set('lighthouse.query_cache.enable', $params[1]);
$configRepository->set('lighthouse.validation_cache.enable', $params[2]);
}

/**
Expand All @@ -62,7 +70,7 @@ public function providePerformanceTuning(): array
return [
'nothing' => [false, false, false],
'query cache' => [false, true, false],
'validation cache' => [false, true, true],
'query + validation cache' => [false, true, true],
'everything' => [true, true, true],
];
}
Expand Down
43 changes: 26 additions & 17 deletions src/GraphQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
use GraphQL\Server\Helper as GraphQLHelper;
use GraphQL\Server\OperationParams;
use GraphQL\Server\RequestError;
use GraphQL\Type\Schema as SchemaType;
use GraphQL\Type\Schema;
use GraphQL\Validator\DocumentValidator;
use GraphQL\Validator\Rules\QueryComplexity;
use Illuminate\Container\Container;
Expand All @@ -28,11 +28,11 @@
use Nuwave\Lighthouse\Events\StartExecution;
use Nuwave\Lighthouse\Events\StartOperationOrOperations;
use Nuwave\Lighthouse\Execution\BatchLoader\BatchLoaderRegistry;
use Nuwave\Lighthouse\Execution\CacheableValidationRulesProvider;
use Nuwave\Lighthouse\Execution\ErrorPool;
use Nuwave\Lighthouse\Schema\SchemaBuilder;
use Nuwave\Lighthouse\Schema\Values\FieldValue;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
use Nuwave\Lighthouse\Support\Contracts\ProvidesCacheableValidationRules;
use Nuwave\Lighthouse\Support\Contracts\ProvidesValidationRules;
use Nuwave\Lighthouse\Support\Utils as LighthouseUtils;

Expand All @@ -46,6 +46,8 @@
*/
class GraphQL
{
protected const CACHEABLE_RULES_ERROR_FREE_RESULT = true;

/**
* Lazily initialized.
*
Expand Down Expand Up @@ -134,9 +136,13 @@ public function executeParsedQueryRaw(
new StartExecution($schema, $query, $variables, $operationName, $context),
);

$errors = $this->validateCacheableRules($schema, $this->schemaBuilder->schemaHash(), $query, $queryHash);
if ($errors !== []) {
return new ExecutionResult(null, $errors);
if ($this->providesValidationRules instanceof CacheableValidationRulesProvider) {
$validationRules = $this->providesValidationRules->cacheableValidationRules();

$errors = $this->validateCacheableRules($validationRules, $schema, $this->schemaBuilder->schemaHash(), $query, $queryHash);
if ($errors !== []) {
return new ExecutionResult(null, $errors);
}
}

$result = GraphQLBase::executeQuery(
Expand Down Expand Up @@ -386,39 +392,42 @@ protected function parseQuery(string $query): DocumentNode
}

/**
* Validate rules that are cacheable. Either by using the cache or by running them.
* Provides a result for cacheable validation rules by running them or retrieving it from the cache.
*
* @param array<string, \GraphQL\Validator\Rules\ValidationRule> $validationRules
*
* @return array<Error>
*/
protected function validateCacheableRules(
SchemaType $schema,
array $validationRules,
Schema $schema,
string $schemaHash,
DocumentNode $query,
?string $queryHash,
): array {
if (! $this->providesValidationRules instanceof ProvidesCacheableValidationRules) {
return [];
}

$validationRules = $this->providesValidationRules->cacheableValidationRules();
foreach ($validationRules as $rule) {
if ($rule instanceof QueryComplexity) {
throw new \InvalidArgumentException('QueryComplexity rule should not be registered in cacheableValidationRules');
throw new \InvalidArgumentException('The QueryComplexity rule must not be registered in cacheableValidationRules, as it depends on variables.');
}
}

if ($queryHash === null) {
return DocumentValidator::validate($schema, $query, $validationRules);
}

$cacheConfig = $this->configRepository->get('lighthouse.validation_cache');

if ($queryHash === null || ! ($cacheConfig['enable'] ?? false)) {
if (! isset($cacheConfig['enable']) || ! $cacheConfig['enable']) {
return DocumentValidator::validate($schema, $query, $validationRules);
}

$cacheKey = "lighthouse:validation:{$schemaHash}:{$queryHash}";

/** @var CacheFactory $cacheFactory */
$cacheFactory = Container::getInstance()->make(CacheFactory::class);
assert($cacheFactory instanceof CacheFactory);

$store = $cacheFactory->store($cacheConfig['store']);
if ($store->get($cacheKey) === true) {
if ($store->get($cacheKey) === self::CACHEABLE_RULES_ERROR_FREE_RESULT) {
return [];
}

Expand All @@ -427,7 +436,7 @@ protected function validateCacheableRules(
return $result;
}

$store->put($cacheKey, true, $cacheConfig['ttl']);
$store->put($cacheKey, self::CACHEABLE_RULES_ERROR_FREE_RESULT, $cacheConfig['ttl']);

return [];
}
Expand Down
14 changes: 8 additions & 6 deletions src/Support/Contracts/ProvidesCacheableValidationRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,26 @@

namespace Nuwave\Lighthouse\Support\Contracts;

/** Allows splitting validation into a cacheable first step and a non-cacheable second step. */
interface ProvidesCacheableValidationRules extends ProvidesValidationRules
{
/**
* A set of rules for the first query validation step.
* Rules where the result depends only on the schema and the query string.
*
* These rules are executed first and their result is cached.
* These rules are executed before non-cacheable rules and may not run
* at all when their result is already cached.
*
* @return array<string, \GraphQL\Validator\Rules\ValidationRule>
*/
public function cacheableValidationRules(): array;

/**
* A set of rules for the second query validation step.
* Rules where the result also depends on variables or other data.
*
* These rules are always executed and not cached.
* These rules are always executed and their result is never cached.
*
* Returning `null` enables all available rules.
* Empty array skips query validation entirely.
* Returning `null` enables all available rules,
* returning `[]` skips query validation entirely.
*
* @return array<string, \GraphQL\Validator\Rules\ValidationRule>|null
*/
Expand Down
6 changes: 3 additions & 3 deletions src/Support/Contracts/ProvidesValidationRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
interface ProvidesValidationRules
{
/**
* A set of rules for query validation step.
* Rules to use for query validation.
*
* Returning `null` enables all available rules.
* Empty array skips query validation entirely.
* Returning `null` enables all available rules,
* returning `[]` skips query validation entirely.
*
* @return array<string, \GraphQL\Validator\Rules\ValidationRule>|null
*/
Expand Down

0 comments on commit 7df6e21

Please sign in to comment.