Skip to content

Commit 1238d43

Browse files
committed
B2B-2658: Implement GraphQL Resolver Cache for Customer query
- added hydration skip procedure
1 parent ce1485f commit 1238d43

File tree

11 files changed

+175
-100
lines changed

11 files changed

+175
-100
lines changed

app/code/Magento/CustomerGraphQl/Model/Customer/ExtractCustomerData.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ function (array $customAttribute) {
101101
$customerData['id'] = null;
102102

103103
$customerData['model'] = $customer;
104-
$customerData['model_id'] = $customer->getId();
105104

106105
//'dob' is deprecated, 'date_of_birth' is used instead.
107106
if (!empty($customerData['dob'])) {

app/code/Magento/CustomerGraphQl/Model/Resolver/CacheKey/FactorProvider/ParentCustomerEntityId.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77

88
namespace Magento\CustomerGraphQl\Model\Resolver\CacheKey\FactorProvider;
99

10+
use Magento\Customer\Api\Data\CustomerInterface;
1011
use Magento\GraphQl\Model\Query\ContextInterface;
11-
use Magento\GraphQlResolverCache\Model\Resolver\Result\CacheKey\ParentValue\PlainValueFactorInterface;
12+
use Magento\GraphQlResolverCache\Model\Resolver\Result\CacheKey\ParentValueFactorInterface;
1213

1314
/**
1415
* Provides customer id from the parent resolved value as a factor to use in the cache key for resolver cache.
1516
*/
16-
class ParentCustomerEntityId implements PlainValueFactorInterface
17+
class ParentCustomerEntityId implements ParentValueFactorInterface
1718
{
1819
/**
1920
* Factor name.
@@ -31,8 +32,22 @@ public function getFactorName(): string
3132
/**
3233
* @inheritDoc
3334
*/
34-
public function getFactorValue(ContextInterface $context, array $plainParentValue = null): string
35+
public function getFactorValue(ContextInterface $context, array $parentValue): string
3536
{
36-
return (string)$plainParentValue['model_id'];
37+
if (isset($parentValue['model_id'])) {
38+
return (string)$parentValue['model_id'];
39+
} else if (isset($parentValue['model']) && $parentValue['model'] instanceof CustomerInterface) {
40+
return (string)$parentValue['model']->getId();
41+
}
42+
throw new \InvalidArgumentException(__CLASS__ . " factor provider requires parent value " .
43+
"to contain customer model id or customer model.");
44+
}
45+
46+
/**
47+
* @inheritDoc
48+
*/
49+
public function isRequiredOrigData(): bool
50+
{
51+
return false;
3752
}
3853
}

app/code/Magento/GraphQlResolverCache/Model/Resolver/Result/CacheKey/Calculator.php

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
use Exception;
1111
use Magento\Framework\ObjectManagerInterface;
1212
use Magento\GraphQl\Model\Query\ContextFactoryInterface;
13-
use Magento\GraphQlResolverCache\Model\Resolver\Result\CacheKey\ParentValue\ProcessedValueFactorInterface;
14-
use Magento\GraphQlResolverCache\Model\Resolver\Result\CacheKey\ParentValue\PlainValueFactorInterface;
1513
use Magento\GraphQlResolverCache\Model\Resolver\Result\ValueProcessorInterface;
1614
use Psr\Log\LoggerInterface;
1715

@@ -74,46 +72,61 @@ public function __construct(
7472
/**
7573
* Calculates the value of resolver cache identifier.
7674
*
77-
* @param array|null $parentResolverData
75+
* @param array|null $parentData
7876
*
7977
* @return string|null
8078
*/
81-
public function calculateCacheKey(?array $parentResolverData = null): ?string
79+
public function calculateCacheKey(?array $parentData = null): ?string
8280
{
8381
if (!$this->factorProviders) {
8482
return null;
8583
}
8684
try {
87-
$context = $this->contextFactory->get();
8885
$this->initializeFactorProviderInstances();
89-
$keys = [];
90-
foreach ($this->factorProviderInstances as $provider) {
91-
if ($provider instanceof ProcessedValueFactorInterface
92-
|| $provider instanceof PlainValueFactorInterface
93-
) {
94-
// trigger data hydration for key calculation if factor needs the hydrated values
95-
if (is_array($parentResolverData) && $provider instanceof ProcessedValueFactorInterface) {
96-
$this->valueProcessor->preProcessParentValue($parentResolverData);
97-
}
98-
$keys[$provider->getFactorName()] = $provider->getFactorValue(
99-
$context,
100-
$parentResolverData
101-
);
102-
} else {
103-
$keys[$provider->getFactorName()] = $provider->getFactorValue(
104-
$context
105-
);
106-
}
107-
}
108-
ksort($keys);
109-
$keysString = strtoupper(implode('|', array_values($keys)));
86+
$factors = $this->getFactors($parentData);
87+
$keysString = strtoupper(implode('|', array_values($factors)));
11088
return hash('sha256', $keysString);
11189
} catch (Exception $e) {
11290
$this->logger->warning("Unable to obtain cache key for resolver results. " . $e->getMessage());
11391
return null;
11492
}
11593
}
11694

95+
/**
96+
* Get key factors from parent data for current context.
97+
*
98+
* @param array|null $parentData
99+
* @return array
100+
*/
101+
private function getFactors(?array $parentData): array
102+
{
103+
$factors = [];
104+
$context = $this->contextFactory->get();
105+
foreach ($this->factorProviderInstances as $factorProvider) {
106+
if ($factorProvider instanceof ParentValueFactorInterface && is_array($parentData)) {
107+
// preprocess data if the data was fetched from cache and has reference key
108+
// and the factorProvider expects processed data (original data from resolver)
109+
if (isset($parentData[ValueProcessorInterface::VALUE_PROCESSING_REFERENCE_KEY])
110+
&& $factorProvider->isRequiredOrigData()
111+
) {
112+
$this->valueProcessor->preProcessParentValue($parentData);
113+
}
114+
// fetch factor value considering parent data
115+
$factors[$factorProvider->getFactorName()] = $factorProvider->getFactorValue(
116+
$context,
117+
$parentData
118+
);
119+
} else {
120+
// get factor value considering only context
121+
$factors[$factorProvider->getFactorName()] = $factorProvider->getFactorValue(
122+
$context
123+
);
124+
}
125+
}
126+
ksort($factors);
127+
return $factors;
128+
}
129+
117130
/**
118131
* Initialize instances of factor providers.
119132
*

app/code/Magento/GraphQlResolverCache/Model/Resolver/Result/CacheKey/ParentValue/PlainValueFactorInterface.php

Lines changed: 0 additions & 26 deletions
This file was deleted.

app/code/Magento/GraphQlResolverCache/Model/Resolver/Result/CacheKey/ParentValue/ProcessedValueFactorInterface.php

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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\GraphQlResolverCache\Model\Resolver\Result\CacheKey;
9+
10+
use Magento\GraphQl\Model\Query\ContextInterface;
11+
12+
/**
13+
* Interface for key factors that are used to calculate the resolver cache key basing on parent value.
14+
*/
15+
interface ParentValueFactorInterface
16+
{
17+
/**
18+
* Name of the cache key factor.
19+
*
20+
* @return string
21+
*/
22+
public function getFactorName(): string;
23+
24+
/**
25+
* Checks if the original resolver data required.
26+
*
27+
* Must return true if any:
28+
* - original resolved data is required to resolve key factor
29+
* - parent resolver cache does not exist (yet)
30+
*
31+
* Can return false if any:
32+
* - parent resolver cache exists AND key factor can be resolved from deserialized unprocessed cached value
33+
* - key factor is one of or combination of the fields exposed in graphql schema
34+
*
35+
* @return bool
36+
*/
37+
public function isRequiredOrigData(): bool;
38+
39+
/**
40+
* Returns the runtime value that should be used as factor.
41+
*
42+
* @param ContextInterface $context
43+
* @param array $parentValue
44+
* @return string
45+
*/
46+
public function getFactorValue(ContextInterface $context, array $parentValue): string;
47+
}

app/code/Magento/GraphQlResolverCache/Model/Resolver/Result/ValueProcessor/FlagGetter/SingleObject.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ class SingleObject implements FlagGetterInterface
1919
*/
2020
public function getFlagFromValue($value): ?array
2121
{
22-
return $value[ValueProcessorInterface::VALUE_HYDRATION_REFERENCE_KEY] ?? null;
22+
return $value[ValueProcessorInterface::VALUE_PROCESSING_REFERENCE_KEY] ?? null;
2323
}
2424
}

app/code/Magento/GraphQlResolverCache/Model/Resolver/Result/ValueProcessor/FlagSetter/ListOfObjects.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class ListOfObjects implements FlagSetterInterface
2020
public function setFlagOnValue(&$value, string $flagValue): void
2121
{
2222
foreach (array_keys($value) as $key) {
23-
$value[$key][ValueProcessorInterface::VALUE_HYDRATION_REFERENCE_KEY] = [
23+
$value[$key][ValueProcessorInterface::VALUE_PROCESSING_REFERENCE_KEY] = [
2424
'cacheKey' => $flagValue,
2525
'index' => $key
2626
];
@@ -33,7 +33,7 @@ public function setFlagOnValue(&$value, string $flagValue): void
3333
public function unsetFlagFromValue(&$value): void
3434
{
3535
foreach (array_keys($value) as $key) {
36-
unset($value[$key][ValueProcessorInterface::VALUE_HYDRATION_REFERENCE_KEY]);
36+
unset($value[$key][ValueProcessorInterface::VALUE_PROCESSING_REFERENCE_KEY]);
3737
}
3838
}
3939
}

app/code/Magento/GraphQlResolverCache/Model/Resolver/Result/ValueProcessor/FlagSetter/SingleObject.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class SingleObject implements FlagSetterInterface
1919
*/
2020
public function setFlagOnValue(&$value, string $flagValue): void
2121
{
22-
$value[ValueProcessorInterface::VALUE_HYDRATION_REFERENCE_KEY] = [
22+
$value[ValueProcessorInterface::VALUE_PROCESSING_REFERENCE_KEY] = [
2323
'cacheKey' => $flagValue,
2424
'index' => 0
2525
];
@@ -30,6 +30,6 @@ public function setFlagOnValue(&$value, string $flagValue): void
3030
*/
3131
public function unsetFlagFromValue(&$value): void
3232
{
33-
unset($value[ValueProcessorInterface::VALUE_HYDRATION_REFERENCE_KEY]);
33+
unset($value[ValueProcessorInterface::VALUE_PROCESSING_REFERENCE_KEY]);
3434
}
3535
}

app/code/Magento/GraphQlResolverCache/Model/Resolver/Result/ValueProcessorInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ interface ValueProcessorInterface
1818
/**
1919
* Key for data processing reference.
2020
*/
21-
public const VALUE_HYDRATION_REFERENCE_KEY = 'value_hydration_reference_key';
21+
public const VALUE_PROCESSING_REFERENCE_KEY = 'value_processing_reference_key';
2222

2323
/**
2424
* Process the cached value after loading from cache for the given resolver.

0 commit comments

Comments
 (0)