Skip to content

Commit 3ea3cbb

Browse files
committed
feat: add APQ plugin
1 parent 8687673 commit 3ea3cbb

File tree

3 files changed

+141
-0
lines changed

3 files changed

+141
-0
lines changed

graphql.services.yml

+15
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ services:
3939
tags:
4040
- { name: cache.context }
4141

42+
# Cache bin for the persisted queries.
43+
cache.graphql.apq:
44+
class: Drupal\Core\Cache\CacheBackendInterface
45+
tags:
46+
- { name: cache.bin }
47+
factory: cache_factory:get
48+
arguments: [graphql_apq]
49+
4250
# Cache bin for the parsed sdl ast.
4351
cache.graphql.ast:
4452
class: Drupal\Core\Cache\CacheBackendInterface
@@ -108,6 +116,13 @@ services:
108116
tags:
109117
- { name: event_subscriber }
110118

119+
# Cache the queries to be persistent.
120+
graphql.apq_subscriber:
121+
class: Drupal\graphql\EventSubscriber\ApqSubscriber
122+
arguments: ['@cache.graphql.apq', '@request_stack']
123+
tags:
124+
- { name: event_subscriber }
125+
111126
# Plugin manager for schemas
112127
plugin.manager.graphql.schema:
113128
class: Drupal\graphql\Plugin\SchemaPluginManager

src/EventSubscriber/ApqSubscriber.php

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
namespace Drupal\graphql\EventSubscriber;
4+
5+
use Drupal\Component\Serialization\Json;
6+
use Drupal\Core\Cache\CacheBackendInterface;
7+
use Drupal\graphql\Event\OperationEvent;
8+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
9+
use Symfony\Component\HttpFoundation\RequestStack;
10+
11+
/**
12+
* Save persisted queries to cache.
13+
*/
14+
class ApqSubscriber implements EventSubscriberInterface {
15+
16+
/**
17+
* The cache to store persisted queries.
18+
*
19+
* @var \Drupal\Core\Cache\CacheBackendInterface
20+
*/
21+
protected $cache;
22+
23+
/**
24+
* The current request.
25+
*
26+
* @var \Symfony\Component\HttpFoundation\Request|null
27+
*/
28+
protected $request;
29+
30+
/**
31+
* Constructs a ApqSubscriber object.
32+
*
33+
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
34+
* The cache to store persisted queries.
35+
* @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
36+
* The request stack.
37+
*/
38+
public function __construct(CacheBackendInterface $cache, RequestStack $requestStack) {
39+
$this->cache = $cache;
40+
$this->request = $requestStack->getCurrentRequest();
41+
}
42+
43+
/**
44+
* Handle operation start events.
45+
*
46+
* @param \Drupal\graphql\Event\OperationEvent $event
47+
* The kernel event object.
48+
*/
49+
public function onBeforeOperation(OperationEvent $event): void {
50+
try {
51+
$json = Json::decode($this->request->getContent());
52+
if (!empty($json['extensions']['persistedQuery']['sha256Hash']) && !empty($json['query'])) {
53+
$this->cache->set($json['extensions']['persistedQuery']['sha256Hash'], $json['query']);
54+
}
55+
56+
}
57+
catch (\Exception $exception) {
58+
}
59+
}
60+
61+
/**
62+
* {@inheritdoc}
63+
*/
64+
public static function getSubscribedEvents() {
65+
return [
66+
OperationEvent::GRAPHQL_OPERATION_BEFORE => 'onBeforeOperation',
67+
];
68+
}
69+
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
namespace Drupal\graphql\Plugin\GraphQL\PersistedQuery;
4+
5+
use Drupal\Core\Cache\CacheBackendInterface;
6+
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
7+
use Drupal\graphql\PersistedQuery\PersistedQueryPluginBase;
8+
use GraphQL\Server\OperationParams;
9+
use GraphQL\Server\RequestError;
10+
use Symfony\Component\DependencyInjection\ContainerInterface;
11+
12+
/**
13+
* Load persisted queries from the cache.
14+
*
15+
* @PersistedQuery(
16+
* id = "automatic_persisted_query",
17+
* label = "Automatic Persisted Query",
18+
* description = "Load persisted queries from the cache."
19+
* )
20+
*/
21+
class AutomaticPersistedQuery extends PersistedQueryPluginBase implements ContainerFactoryPluginInterface {
22+
23+
/**
24+
* The cache to store persisted queries.
25+
*
26+
* @var \Drupal\Core\Cache\CacheBackendInterface
27+
*/
28+
protected $cache;
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function __construct(array $configuration, $plugin_id, $plugin_definition, CacheBackendInterface $cache) {
34+
parent::__construct($configuration, $plugin_id, $plugin_definition);
35+
36+
$this->cache = $cache;
37+
}
38+
39+
/**
40+
* {@inheritdoc}
41+
*/
42+
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
43+
return new static($configuration, $plugin_id, $plugin_definition, $container->get('cache.graphql.apq'));
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
public function getQuery($id, OperationParams $operation) {
50+
if ($query = $this->cache->get($id)) {
51+
return $query->data;
52+
}
53+
throw new RequestError('PersistedQueryNotFound');
54+
}
55+
56+
}

0 commit comments

Comments
 (0)