Skip to content

Commit 58a9b74

Browse files
authored
Fixing sub request buffer and cache metadata collection. (#547)
1 parent e0918cc commit 58a9b74

8 files changed

Lines changed: 83 additions & 22 deletions

File tree

modules/graphql_core/src/Plugin/GraphQL/Fields/Blocks/BlocksByRegion.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ protected function resolveValues($value, array $args, ResolveContext $context, R
141141
});
142142

143143
return function ($value, array $args, ResolveContext $context, ResolveInfo $info) use ($resolve) {
144+
/** @var \Drupal\graphql\GraphQL\Cache\CacheableValue $response */
145+
$response = $resolve();
144146
$metadata = new CacheableMetadata();
145147
$metadata->addCacheTags(['config:block_list']);
146148
$blocks = array_map(function (Block $block) {
@@ -151,10 +153,10 @@ protected function resolveValues($value, array $args, ResolveContext $context, R
151153
else {
152154
return $block;
153155
}
154-
}, $resolve());
156+
}, $response->getValue());
155157

156158
foreach ($blocks as $block) {
157-
yield new CacheableValue($block, [$metadata]);
159+
yield new CacheableValue($block, [$metadata, $response]);
158160
}
159161
};
160162
}

modules/graphql_core/src/Plugin/GraphQL/Fields/Breadcrumbs/Breadcrumbs.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Drupal\Core\Routing\RouteMatchInterface;
88
use Drupal\Core\Url;
99
use Drupal\graphql\GraphQL\Buffers\SubRequestBuffer;
10+
use Drupal\graphql\GraphQL\Cache\CacheableValue;
1011
use Drupal\graphql\GraphQL\Execution\ResolveContext;
1112
use Drupal\graphql\Plugin\GraphQL\Fields\FieldPluginBase;
1213
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -101,9 +102,12 @@ protected function resolveValues($value, array $args, ResolveContext $context, R
101102
});
102103

103104
return function ($value, array $args, ResolveContext $context, ResolveInfo $info) use ($resolve) {
104-
$links = $resolve();
105+
/** @var \Drupal\graphql\GraphQL\Cache\CacheableValue $response */
106+
$response = $resolve();
107+
$links = $response->getValue();
108+
105109
foreach ($links as $link) {
106-
yield $link;
110+
yield new CacheableValue($link, [$response]);
107111
}
108112
};
109113
}

modules/graphql_core/src/Plugin/GraphQL/Fields/LanguageSwitch/LanguageSwitchLinks.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
88
use Drupal\Core\Url;
99
use Drupal\graphql\GraphQL\Buffers\SubRequestBuffer;
10+
use Drupal\graphql\GraphQL\Cache\CacheableValue;
1011
use Drupal\graphql\GraphQL\Execution\ResolveContext;
1112
use Drupal\graphql\Plugin\GraphQL\Fields\FieldPluginBase;
1213
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -82,16 +83,18 @@ protected function resolveValues($value, array $args, ResolveContext $context, R
8283
});
8384

8485
return function () use ($resolve) {
85-
list($current, $links) = $resolve();
86+
/** @var \Drupal\graphql\GraphQL\Cache\CacheableValue $response */
87+
$response = $resolve();
88+
list($current, $links) = $response->getValue();
8689

8790
if (!empty($links->links)) {
8891
foreach ($links->links as $link) {
8992
// Yield the link array and the language object of the language
9093
// context resolved from the sub-request.
91-
yield [
94+
yield new CacheableValue([
9295
'link' => $link,
9396
'context' => $current,
94-
];
97+
], [$response]);
9598
}
9699
}
97100
};

modules/graphql_core/src/Plugin/GraphQL/Fields/Routing/InternalUrl/InternalRequest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
66
use Drupal\Core\Url;
77
use Drupal\graphql\GraphQL\Buffers\SubRequestBuffer;
8+
use Drupal\graphql\GraphQL\Cache\CacheableValue;
89
use Drupal\graphql\GraphQL\Execution\ResolveContext;
910
use Drupal\graphql\Plugin\GraphQL\Fields\FieldPluginBase;
1011
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -114,7 +115,9 @@ protected function resolveValues($value, array $args, ResolveContext $context, R
114115
});
115116

116117
return function ($value, array $args, ResolveContext $context, ResolveInfo $info) use ($resolve) {
117-
yield $resolve();
118+
/** @var \Drupal\graphql\GraphQL\Cache\CacheableValue $response */
119+
$response = $resolve();
120+
yield new CacheableValue($response->getValue(), [$response]);
118121
};
119122
}
120123
}

modules/graphql_core/src/Plugin/GraphQL/Fields/Routing/RouteEntity.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,11 @@ protected function resolveEntityTranslation(EntityInterface $entity, Url $url, a
172172
});
173173

174174
return function ($value, array $args, ResolveContext $context, ResolveInfo $info) use ($resolve, $entity) {
175-
$language = $resolve();
176-
$entity = $this->entityRepository->getTranslationFromContext($entity, $language);
175+
/** @var \Drupal\graphql\GraphQL\Cache\CacheableValue $response */
176+
$response = $resolve();
177+
$entity = $this->entityRepository->getTranslationFromContext($entity, $response->getValue());
178+
$entity->addCacheableDependency($response);
179+
177180
return $this->resolveEntity($entity, $value, $args, $info);
178181
};
179182
}

src/Controller/SubrequestExtractionController.php

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use Drupal\Core\Controller\ControllerBase;
66
use Drupal\Core\Language\LanguageManagerInterface;
7+
use Drupal\Core\Render\RenderContext;
8+
use Drupal\Core\Render\RendererInterface;
79
use Drupal\graphql\GraphQL\Buffers\SubRequestResponse;
810
use Symfony\Component\DependencyInjection\ContainerInterface;
911
use Symfony\Component\HttpFoundation\RequestStack;
@@ -20,22 +22,38 @@ class SubrequestExtractionController extends ControllerBase {
2022
*/
2123
protected $requestStack;
2224

25+
/**
26+
* The renderer service.
27+
*
28+
* @var \Drupal\Core\Render\RendererInterface
29+
*/
30+
protected $renderer;
31+
2332
/**
2433
* {@inheritdoc}
2534
*/
2635
public static function create(ContainerInterface $container) {
2736
return new static(
2837
$container->get('request_stack'),
29-
$container->get('language_manager')
38+
$container->get('language_manager'),
39+
$container->get('renderer')
3040
);
3141
}
3242

3343
/**
34-
* {@inheritdoc}
44+
* SubrequestExtractionController constructor.
45+
*
46+
* @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
47+
* The request stack.
48+
* @param \Drupal\Core\Language\LanguageManagerInterface $languageManager
49+
* The language manager service.
50+
* @param \Drupal\Core\Render\RendererInterface $renderer
51+
* The rewnderer service.
3552
*/
36-
public function __construct(RequestStack $requestStack, LanguageManagerInterface $languageManager) {
53+
public function __construct(RequestStack $requestStack, LanguageManagerInterface $languageManager, RendererInterface $renderer) {
3754
$this->requestStack = $requestStack;
3855
$this->languageManager = $languageManager;
56+
$this->renderer = $renderer;
3957
}
4058

4159
/**
@@ -51,7 +69,18 @@ public function extract() {
5169
// TODO: Remove this once https://www.drupal.org/project/drupal/issues/2940036#comment-12479912 is resolved.
5270
$this->languageManager->reset();
5371

54-
return new SubRequestResponse($callback());
72+
// Collect any potentially leaked cache metadata released by the callback.
73+
$context = new RenderContext();
74+
$result = $this->renderer->executeInRenderContext($context, function () use ($callback) {
75+
return $callback();
76+
});
77+
78+
$response = new SubRequestResponse($result);
79+
if (!$context->isEmpty()) {
80+
$response->addCacheableDependency($context->pop());
81+
}
82+
83+
return $response;
5584
}
5685

5786
}

src/GraphQL/Buffers/SubRequestBuffer.php

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace Drupal\graphql\GraphQL\Buffers;
44

5+
use Drupal\Core\Cache\CacheableDependencyInterface;
56
use Drupal\Core\Url;
7+
use Drupal\graphql\GraphQL\Cache\CacheableValue;
68
use Symfony\Component\HttpFoundation\Request;
79
use Symfony\Component\HttpFoundation\RequestStack;
810
use Symfony\Component\HttpKernel\HttpKernelInterface;
@@ -60,20 +62,27 @@ public function add(Url $url, callable $extract) {
6062
* {@inheritdoc}
6163
*/
6264
protected function getBufferId($item) {
63-
/** @var \Drupal\Core\Url $url */
64-
$url = $item['url'];
65-
return $url->toString();
65+
/** @var \Drupal\Core\GeneratedUrl $url */
66+
$url = $item['url']->toString(TRUE);
67+
68+
return hash('sha256', json_encode([
69+
'url' => $url->getGeneratedUrl(),
70+
'tags' => $url->getCacheTags(),
71+
'contexts' => $url->getCacheContexts(),
72+
'age' => $url->getCacheMaxAge(),
73+
]));
6674
}
6775

6876
/**
6977
* {@inheritdoc}
7078
*/
7179
public function resolveBufferArray(array $buffer) {
72-
/** @var \Drupal\Core\Url $url */
73-
$url = reset($buffer)['url'];
80+
/** @var \Drupal\Core\GeneratedUrl $url */
81+
$url = reset($buffer)['url']->toString(TRUE);
82+
7483
$currentRequest = $this->requestStack->getCurrentRequest();
7584
$request = Request::create(
76-
$url->getOption('routed_path') ?: $url->toString(),
85+
$url->getGeneratedUrl(),
7786
'GET',
7887
$currentRequest->query->all(),
7988
$currentRequest->cookies->all(),
@@ -93,6 +102,9 @@ public function resolveBufferArray(array $buffer) {
93102

94103
/** @var \Drupal\graphql\GraphQL\Buffers\SubRequestResponse $response */
95104
$response = $this->httpKernel->handle($request, HttpKernelInterface::SUB_REQUEST);
105+
if ($url instanceof CacheableDependencyInterface) {
106+
$response->addCacheableDependency($url);
107+
}
96108

97109
// TODO:
98110
// Remove the request stack manipulation once the core issue described at
@@ -101,7 +113,9 @@ public function resolveBufferArray(array $buffer) {
101113
$this->requestStack->pop();
102114
}
103115

104-
return $response->getResult();
116+
return array_map(function ($value) use ($response) {
117+
return new CacheableValue($value, [$response]);
118+
}, $response->getResult());
105119
}
106120

107121
}

src/GraphQL/Buffers/SubRequestResponse.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
namespace Drupal\graphql\GraphQL\Buffers;
44

5+
use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
6+
use Drupal\Core\Cache\RefinableCacheableDependencyTrait;
57
use Symfony\Component\HttpFoundation\Response;
68

7-
class SubRequestResponse extends Response {
9+
class SubRequestResponse extends Response implements RefinableCacheableDependencyInterface {
10+
use RefinableCacheableDependencyTrait;
811

912
/**
1013
* The request result.

0 commit comments

Comments
 (0)