Skip to content

Commit cd08acf

Browse files
Merge pull request #8242 from magento-arcticfoxes/B2B-2658
B2B-2658: Implement GraphQL Resolver Cache for Customer query
2 parents 35e8e43 + 665d6e4 commit cd08acf

File tree

78 files changed

+4515
-308
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+4515
-308
lines changed

app/code/Magento/CmsGraphQl/Model/Resolver/Block/ResolverCacheIdentity.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
use Magento\Cms\Api\Data\BlockInterface;
1111
use Magento\Cms\Model\Block;
12-
use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface;
12+
use Magento\GraphQlResolverCache\Model\Resolver\Result\Cache\IdentityInterface;
1313

1414
class ResolverCacheIdentity implements IdentityInterface
1515
{
@@ -19,12 +19,9 @@ class ResolverCacheIdentity implements IdentityInterface
1919
private $cacheTag = Block::CACHE_TAG;
2020

2121
/**
22-
* Get block identities from resolved data
23-
*
24-
* @param array $resolvedData
25-
* @return string[]
22+
* @inheritdoc
2623
*/
27-
public function getIdentities(array $resolvedData): array
24+
public function getIdentities($resolvedData, ?array $parentResolvedData = null): array
2825
{
2926
$ids = [];
3027
$items = $resolvedData['items'] ?? [];

app/code/Magento/CmsGraphQl/Model/Resolver/Page/ResolverCacheIdentity.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
use Magento\Cms\Api\Data\PageInterface;
1111
use Magento\Cms\Model\Page;
12-
use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface;
12+
use Magento\GraphQlResolverCache\Model\Resolver\Result\Cache\IdentityInterface;
1313

1414
/**
1515
* Identity for resolved CMS page for resolver cache type
@@ -22,12 +22,9 @@ class ResolverCacheIdentity implements IdentityInterface
2222
private $cacheTag = Page::CACHE_TAG;
2323

2424
/**
25-
* Get page ID from resolved data
26-
*
27-
* @param array $resolvedData
28-
* @return string[]
25+
* @inheritdoc
2926
*/
30-
public function getIdentities(array $resolvedData): array
27+
public function getIdentities($resolvedData, ?array $parentResolvedData = null): array
3128
{
3229
return empty($resolvedData[PageInterface::PAGE_ID]) ?
3330
[] : [sprintf('%s_%s', $this->cacheTag, $resolvedData[PageInterface::PAGE_ID])];

app/code/Magento/CmsGraphQl/Test/Integration/Model/Resolver/PageTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
use Magento\Framework\App\Cache\Type\FrontendPool;
1515
use Magento\Framework\ObjectManagerInterface;
1616
use Magento\GraphQl\Service\GraphQlRequest;
17-
use Magento\GraphQlCache\Model\Cache\Query\Resolver\Result\Type as GraphQlResolverCache;
18-
use Magento\GraphQlCache\Model\Plugin\Query\Resolver\Result\Cache as ResolverResultCachePlugin;
17+
use Magento\GraphQlResolverCache\Model\Plugin\Resolver\Cache as ResolverResultCachePlugin;
18+
use Magento\GraphQlResolverCache\Model\Resolver\Result\Type as GraphQlResolverCache;
1919
use Magento\TestFramework\Helper\Bootstrap;
2020
use PHPUnit\Framework\TestCase;
2121

app/code/Magento/CmsGraphQl/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"magento/framework": "*",
88
"magento/module-cms": "*",
99
"magento/module-widget": "*",
10-
"magento/module-store": "*"
10+
"magento/module-store": "*",
11+
"magento/module-graph-ql-resolver-cache": "*"
1112
},
1213
"suggest": {
1314
"magento/module-graph-ql": "*",

app/code/Magento/CmsGraphQl/etc/di.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77
-->
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
9-
<type name="Magento\GraphQlCache\Model\Cache\Query\Resolver\Result\TagResolver">
9+
<type name="Magento\GraphQlResolverCache\Model\Resolver\Result\TagResolver">
1010
<arguments>
1111
<argument name="invalidatableObjectTypes" xsi:type="array">
1212
<item name="Magento\Cms\Api\Data\PageInterface" xsi:type="string">

app/code/Magento/CmsGraphQl/etc/graphql/di.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
</argument>
1919
</arguments>
2020
</type>
21-
<type name="Magento\GraphQlCache\Model\Cache\Query\Resolver\Result\ResolverIdentityClassLocator">
21+
<type name="Magento\GraphQlResolverCache\Model\Resolver\Result\ResolverIdentityClassProvider">
2222
<arguments>
2323
<argument name="cacheableResolverClassNameIdentityMap" xsi:type="array">
2424
<item name="Magento\CmsGraphQl\Model\Resolver\Page" xsi:type="string">

app/code/Magento/CmsGraphQl/etc/module.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<module name="Magento_CmsGraphQl">
1010
<sequence>
1111
<module name="Magento_GraphQl"/>
12+
<module name="Magento_GraphQlResolverCache"/>
1213
</sequence>
1314
</module>
1415
</config>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CustomerGraphQl\Model\Resolver\Cache\Customer\Address;
9+
10+
use Magento\Customer\Model\Customer;
11+
use Magento\Framework\App\Cache\Tag\StrategyInterface;
12+
13+
/**
14+
* Provides the customer record identity to invalidate on address change.
15+
*/
16+
class TagsStrategy implements StrategyInterface
17+
{
18+
/**
19+
* @inheritDoc
20+
*/
21+
public function getTags($object)
22+
{
23+
return [sprintf('%s_%s', Customer::ENTITY, $object->getCustomerId())];
24+
}
25+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CustomerGraphQl\Model\Resolver\Cache\Customer;
9+
10+
use Magento\Customer\Model\Data\Customer;
11+
use Magento\Framework\EntityManager\HydratorPool;
12+
use Magento\Framework\EntityManager\TypeResolver;
13+
use Magento\GraphQlResolverCache\Model\Resolver\Result\DehydratorInterface;
14+
15+
/**
16+
* Customer resolver data dehydrator to create snapshot data necessary to restore model.
17+
*/
18+
class ModelDehydrator implements DehydratorInterface
19+
{
20+
/**
21+
* @var TypeResolver
22+
*/
23+
private TypeResolver $typeResolver;
24+
25+
/**
26+
* @var HydratorPool
27+
*/
28+
private HydratorPool $hydratorPool;
29+
30+
/**
31+
* @param HydratorPool $hydratorPool
32+
* @param TypeResolver $typeResolver
33+
*/
34+
public function __construct(
35+
HydratorPool $hydratorPool,
36+
TypeResolver $typeResolver
37+
) {
38+
$this->typeResolver = $typeResolver;
39+
$this->hydratorPool = $hydratorPool;
40+
}
41+
42+
/**
43+
* @inheritdoc
44+
*/
45+
public function dehydrate(array &$resolvedValue): void
46+
{
47+
if (isset($resolvedValue['model']) && $resolvedValue['model'] instanceof Customer) {
48+
/** @var Customer $model */
49+
$model = $resolvedValue['model'];
50+
$entityType = $this->typeResolver->resolve($model);
51+
$resolvedValue['model_data'] = $this->hydratorPool->getHydrator($entityType)
52+
->extract($model);
53+
$resolvedValue['model_entity_type'] = $entityType;
54+
$resolvedValue['model_id'] = $model->getId();
55+
}
56+
}
57+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CustomerGraphQl\Model\Resolver\Cache\Customer;
9+
10+
use Magento\Customer\Model\Data\Customer;
11+
use Magento\Customer\Model\Data\CustomerFactory;
12+
use Magento\Framework\EntityManager\HydratorPool;
13+
use Magento\GraphQlResolverCache\Model\Resolver\Result\HydratorInterface;
14+
15+
/**
16+
* Customer resolver data hydrator to rehydrate propagated model.
17+
*/
18+
class ModelHydrator implements HydratorInterface
19+
{
20+
/**
21+
* @var CustomerFactory
22+
*/
23+
private CustomerFactory $customerFactory;
24+
25+
/**
26+
* @var Customer[]
27+
*/
28+
private array $customerModels = [];
29+
30+
/**
31+
* @var HydratorPool
32+
*/
33+
private HydratorPool $hydratorPool;
34+
35+
/**
36+
* @param CustomerFactory $customerFactory
37+
* @param HydratorPool $hydratorPool
38+
*/
39+
public function __construct(
40+
CustomerFactory $customerFactory,
41+
HydratorPool $hydratorPool
42+
) {
43+
$this->hydratorPool = $hydratorPool;
44+
$this->customerFactory = $customerFactory;
45+
}
46+
47+
/**
48+
* @inheritdoc
49+
*/
50+
public function hydrate(array &$resolverData): void
51+
{
52+
if (isset($this->customerModels[$resolverData['model_id']])) {
53+
$resolverData['model'] = $this->customerModels[$resolverData['model_id']];
54+
} else {
55+
$hydrator = $this->hydratorPool->getHydrator($resolverData['model_entity_type']);
56+
$model = $this->customerFactory->create();
57+
$hydrator->hydrate($model, $resolverData['model_data']);
58+
$this->customerModels[$resolverData['model_id']] = $model;
59+
$resolverData['model'] = $this->customerModels[$resolverData['model_id']];
60+
}
61+
}
62+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CustomerGraphQl\Model\Resolver\Cache\Customer;
9+
10+
use Magento\Customer\Model\Customer;
11+
use Magento\GraphQlResolverCache\Model\Resolver\Result\Cache\IdentityInterface;
12+
13+
/**
14+
* Identity for resolved Customer for resolver cache type
15+
*/
16+
class ResolverCacheIdentity implements IdentityInterface
17+
{
18+
/**
19+
* @var string
20+
*/
21+
private $cacheTag = Customer::ENTITY;
22+
23+
/**
24+
* @inheritdoc
25+
*/
26+
public function getIdentities($resolvedData, ?array $parentResolvedData = null): array
27+
{
28+
return empty($resolvedData['model']->getId()) ?
29+
[] : [sprintf('%s_%s', $this->cacheTag, $resolvedData['model']->getId())];
30+
}
31+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CustomerGraphQl\Model\Resolver\Cache\Customer;
9+
10+
use Magento\Customer\Model\Customer;
11+
use Magento\Framework\App\Cache\Tag\StrategyInterface;
12+
13+
/**
14+
* Customer entity tag resolver strategy.
15+
*/
16+
class TagsStrategy implements StrategyInterface
17+
{
18+
/**
19+
* @inheritDoc
20+
*/
21+
public function getTags($object)
22+
{
23+
return [sprintf('%s_%s', Customer::ENTITY, $object->getId())];
24+
}
25+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CustomerGraphQl\Model\Resolver\Cache\Subscriber;
9+
10+
use Magento\GraphQlResolverCache\Model\Resolver\Result\Cache\IdentityInterface;
11+
12+
/**
13+
* Identity for resolved Customer subscription status for resolver cache type
14+
*/
15+
class ResolverCacheIdentity implements IdentityInterface
16+
{
17+
/**
18+
* @var string
19+
*/
20+
private $cacheTag = 'SUBSCRIBER';
21+
22+
/**
23+
* @inheritdoc
24+
*/
25+
public function getIdentities($resolvedData, ?array $parentResolvedData = null): array
26+
{
27+
return empty($parentResolvedData['model']->getId()) ?
28+
[] : [sprintf('%s_%s', $this->cacheTag, $parentResolvedData['model']->getId())];
29+
}
30+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CustomerGraphQl\Model\Resolver\Cache\Subscriber;
9+
10+
use Magento\Customer\Model\Customer;
11+
use Magento\Framework\App\Cache\Tag\StrategyInterface;
12+
13+
/**
14+
* Customer subscriber entity tag resolver strategy.
15+
*/
16+
class TagsStrategy implements StrategyInterface
17+
{
18+
/**
19+
* @inheritDoc
20+
*/
21+
public function getTags($object)
22+
{
23+
return [sprintf('%s_%s', "SUBSCRIBER", $object->getCustomerId())];
24+
}
25+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CustomerGraphQl\Model\Resolver\CacheKey\FactorProvider;
9+
10+
use Magento\GraphQl\Model\Query\ContextInterface;
11+
use Magento\GraphQlResolverCache\Model\Resolver\Result\CacheKey\GenericFactorProviderInterface;
12+
13+
/**
14+
* Provides logged-in customer id as a factor to use in the cache key for resolver cache.
15+
*/
16+
class CurrentCustomerId implements GenericFactorProviderInterface
17+
{
18+
/**
19+
* Factor name.
20+
*/
21+
private const NAME = "CUSTOMER_ID";
22+
23+
/**
24+
* @inheritdoc
25+
*/
26+
public function getFactorName(): string
27+
{
28+
return static::NAME;
29+
}
30+
31+
/**
32+
* @inheritDoc
33+
*/
34+
public function getFactorValue(ContextInterface $context): string
35+
{
36+
return (string)$context->getUserId();
37+
}
38+
}

0 commit comments

Comments
 (0)