Skip to content

Commit

Permalink
LYNX-176: Fix unrelated caches invalidation (#123)
Browse files Browse the repository at this point in the history
* LYNX-151: Cache identity for attributeForms query

* LYNX-151: Tests [in progress]

* LYNX-151: Cache identity for attributeForms query - tests

* LYNX-151: Cache identity for attributeForms query - pre CR changes

* LYNX-151: Cache identity for attributeForms query - pre CR changes

* LYNX-151: Cache identity for attributeForms query - pre CR changes

* LYNX-151: Cache identity for attributeForms query - pre CR changes

* LYNX-151: Cache identity for attributeForms query - pre CR changes

* LYNX-151: Add cache invalidation test

* LYNX-151: Add cache invalidation test

* LYNX-151: Add tests for cahce invalidation for shared attribute (two forms)

* LYNX-151: Add cache invalidation test - refactoring (cont.)

* LYNX-151: Test for multiple stores

* LYNX-151: Refactoring

* LYNX-151: Work in progress

* LYNX-151: Add cache tag for AttributesForm query

* LYNX-151: Cache identity for attributeForms query - bugfixes, refactoring

* LYNX-151: CR changes

* LYNX-151: CR changes

* LYNX-151: CR changes

* LYNX-151: Refactoring, bugfixing

* LYNX-151: Refactoring, bugfixing; adding more specific cache tagging for attributesForm

* LYNX-151: Refactoring; bugfixing; test coverage improvements

* LNX-151: Fix static tests; cleanup the code

* LYNX-151: Refactoring

* LYNX-151: Refactoring

* LYNX-151: Refactoring

* LYNX-151: Refactoring

* LYNX-151: Refactoring

* LYNX-151: Refactoring; bugfixing; revert unnecessary changes

* LYNX-151: Refactoring

* LYNX-151: Refactoring

* LYNX-151: Refactoring

* LYNX-151: Refactoring

* LYNX-151: pre-CR changes

* LYNX-151: Bugfixing

* LYNX-176: Move invalidation of attributesList caches to InvalidateAttributeRelatedCaches plugin

* LYNX-171: Some refactoring; remove cache tag creation for attributesList from AttributePlugin

* LYNX-151: Fix for Static tests; refactoring

* LYNX-151: Refactoring

* LYNX-151: Refactoring

* LYNX-176: Refactoring; added Cache Id headers to AttributesListCache tests

* LYNX-176: Refactoring; remove unnecessary tag(s) invalidation from InvalidateAttributeRelatedCaches

* LYNX-176: Refactoring; added tests to cover additional scenarios

* LYNX-176: Refacting; fix issue with tag for entity types

* LYNX-176: Refactoring

* LYNX-176: Refactoring

* LYNX-176: Tests fixes; refactoring

* LYNX-176: CR changes; refactoring

* LYNX-176: delete temp file

* LYNX-176: Formatting
  • Loading branch information
bl4de authored Jul 5, 2023
1 parent 41883fa commit a796656
Show file tree
Hide file tree
Showing 11 changed files with 1,053 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public function clean()
$this->cache->clean(
[
Type::CACHE_TAG,
Attribute::CACHE_TAG,
Attribute::CACHE_TAG
]
);
}
Expand Down
34 changes: 16 additions & 18 deletions app/code/Magento/Eav/Model/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,8 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

/**
* EAV attribute resource model (Using Forms)
*
* @method \Magento\Eav\Model\Attribute\Data\AbstractData|null getDataModel()
* Get data model linked to attribute or null.
*
* @author Magento Core Team <core@magentocommerce.com>
*/
namespace Magento\Eav\Model;

use Magento\Store\Model\Website;
Expand All @@ -23,14 +16,7 @@
class Attribute extends \Magento\Eav\Model\Entity\Attribute
{
/**
* Name of the module
* Override it
*/
//const MODULE_NAME = 'Magento_Eav';

/**
* Name of the module
* Override it
* @var string
*/
protected $_eventObject = 'attribute';

Expand Down Expand Up @@ -80,7 +66,7 @@ public function afterSave()
}

/**
* Return forms in which the attribute
* Return forms in which the attribute is being used
*
* @return array
*/
Expand Down Expand Up @@ -110,6 +96,18 @@ public function getValidateRules()
return [];
}

/**
* @inheritdoc
*/
public function setData($key, $value = null): Attribute
{
if ($key === 'used_in_forms') {
$this->setOrigData('used_in_forms', $this->getData('used_in_forms') ?? []);
}
parent::setData($key, $value);
return $this;
}

/**
* Set validate rules
*
Expand Down Expand Up @@ -188,7 +186,7 @@ public function getMultilineCount()
}

/**
* {@inheritdoc}
* @inheritdoc
*/
public function afterDelete()
{
Expand Down
50 changes: 50 additions & 0 deletions app/code/Magento/Eav/Model/Cache/AttributesFormIdentity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\Eav\Model\Cache;

use Magento\Framework\Api\AttributeInterface;
use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface;
use Magento\Eav\Model\Entity\Attribute;

/**
* Cache identity provider for attributes form query
*/
class AttributesFormIdentity implements IdentityInterface
{
public const CACHE_TAG = 'EAV_FORM';
/**
* @inheritDoc
*/
public function getIdentities(array $resolvedData): array
{
if (empty($resolvedData['items'])) {
return [];
}

$identities = [];

if ($resolvedData['formCode'] !== '') {
$identities[] = sprintf(
"%s_%s_FORM",
self::CACHE_TAG,
$resolvedData['formCode'] ?? ''
);
}

foreach ($resolvedData['items'] as $item) {
if ($item['attribute'] instanceof AttributeInterface) {
$identities[] = sprintf(
"%s_%s",
Attribute::CACHE_TAG,
$item['attribute']->getAttributeId()
);
}
}
return $identities;
}
}
2 changes: 1 addition & 1 deletion app/code/Magento/Eav/Model/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public function clear()
$this->_cache->clean(
[
\Magento\Eav\Model\Cache\Type::CACHE_TAG,
\Magento\Eav\Model\Entity\Attribute::CACHE_TAG,
\Magento\Eav\Model\Entity\Attribute::CACHE_TAG
]
);
return $this;
Expand Down
32 changes: 31 additions & 1 deletion app/code/Magento/Eav/Model/Entity/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Stdlib\DateTime;
use Magento\Framework\Stdlib\DateTime\DateTimeFormatterInterface;
use Magento\Eav\Model\Config;
use Magento\Eav\Model\Cache\AttributesFormIdentity;

/**
* EAV Entity attribute model
Expand Down Expand Up @@ -522,7 +524,35 @@ public function getSortWeight($setId)
*/
public function getIdentities()
{
return [self::CACHE_TAG . '_' . $this->getId()];
$identities = [self::CACHE_TAG . '_' . $this->getId()];

if (($this->hasDataChanges() || $this->isDeleted())) {
$identities[] = sprintf(
"%s_%s_ENTITY",
Config::ENTITIES_CACHE_ID,
strtoupper($this->getEntityType()->getEntityTypeCode())
);

$formsUsedBeforeChange = $this->getOrigData('used_in_forms') ?? [];
$usedInForms = $this->getUsedInForms() ?? [];

if ($formsUsedBeforeChange != $usedInForms) {
$formsToInvalidate = array_merge(
array_diff($formsUsedBeforeChange, $usedInForms),
array_diff($usedInForms, $formsUsedBeforeChange)
);

foreach ($formsToInvalidate as $form) {
$identities[] = sprintf(
"%s_%s_FORM",
AttributesFormIdentity::CACHE_TAG,
$form
);
};
}
}

return $identities;
}

/**
Expand Down
20 changes: 14 additions & 6 deletions app/code/Magento/EavGraphQl/Model/Resolver/AttributesForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,26 +51,34 @@ public function resolve(
array $value = null,
array $args = null
) {

if (empty($args['formCode'])) {
throw new GraphQlInputException(__('Required parameter "%1" of type string.', 'formCode'));
}

$attributes = $this->getAttributesFormComposite->execute($args['formCode']);
if ($this->isAnAdminForm($args['formCode']) || $attributes === null) {
$formCode = $args['formCode'];

$attributes = $this->getAttributesFormComposite->execute($formCode);
if ($this->isAnAdminForm($formCode) || $attributes === null) {
return [
'items' => [],
'errors' => [
[
'type' => 'ENTITY_NOT_FOUND',
'message' => (string) __('Form "%form" could not be found.', ['form' => $args['formCode']])
'message' => (string) __('Form "%form" could not be found.', ['form' => $formCode])
]
]
];
}

return $this->getAttributesMetadata->execute(
$attributes,
(int)$context->getExtensionAttributes()->getStore()->getId()
return array_merge(
[
'formCode' => $formCode
],
$this->getAttributesMetadata->execute(
$attributes,
(int)$context->getExtensionAttributes()->getStore()->getId()
)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,40 @@
namespace Magento\EavGraphQl\Model\Resolver\Cache;

use Magento\Framework\GraphQl\Query\Resolver\IdentityInterface;
use Magento\Framework\Api\AttributeInterface;
use Magento\Eav\Model\Config;
use Magento\Eav\Model\Entity\Attribute;

/**
* Cache identity provider for attributes list query results.
*/
class AttributesListIdentity implements IdentityInterface
{
public const CACHE_TAG = 'ATTRIBUTES_LIST';

/**
* @inheritDoc
*/
public function getIdentities(array $resolvedData): array
{
if (empty($resolvedData['items'])) {
if (empty($resolvedData['items']) || !is_array($resolvedData['items'][0])) {
return [];
}

if (!is_array($resolvedData['items'][0])) {
return [];
$item = $resolvedData['items'][0];
$identities = [];

if ($item['entity_type'] !== '') {
$identities[] = Config::ENTITIES_CACHE_ID . "_" . $item['entity_type'] . "_ENTITY";
}

return [sprintf(
"%s_%s",
self::CACHE_TAG,
$resolvedData['items'][0]['entity_type']
)];
foreach ($resolvedData['items'] as $item) {
if ($item['attribute'] instanceof AttributeInterface) {
$identities[] = sprintf(
"%s_%s",
Attribute::CACHE_TAG,
$item['attribute']->getAttributeId()
);
}
}
return $identities;
}
}
4 changes: 1 addition & 3 deletions app/code/Magento/EavGraphQl/Plugin/Eav/AttributePlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
namespace Magento\EavGraphQl\Plugin\Eav;

use Magento\Eav\Model\Entity\Attribute;
use Magento\EavGraphQl\Model\Resolver\Cache\AttributesListIdentity;
use Magento\Framework\Api\AttributeInterface;

/**
Expand Down Expand Up @@ -36,8 +35,7 @@ public function afterGetIdentities(Attribute $subject, array $result): array
$subject->getOrigData(AttributeInterface::ATTRIBUTE_CODE)
?? $subject->getData(AttributeInterface::ATTRIBUTE_CODE)
)
],
[AttributesListIdentity::CACHE_TAG.'_'.strtoupper($subject->getEntityType()->getEntityTypeCode())]
]
);
}
}
5 changes: 4 additions & 1 deletion app/code/Magento/EavGraphQl/etc/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ type Query {
@cache(cacheIdentity: "Magento\\EavGraphQl\\Model\\Resolver\\Cache\\CustomAttributeMetadataIdentity")
@deprecated(reason: "Use `customAttributeMetadataV2` query instead.")
customAttributeMetadataV2(attributes: [AttributeInput!]): AttributesMetadataOutput! @resolver(class: "Magento\\EavGraphQl\\Model\\Resolver\\AttributesMetadata") @doc(description: "Retrieve EAV attributes metadata.") @cache(cacheIdentity: "Magento\\EavGraphQl\\Model\\Resolver\\Cache\\CustomAttributeMetadataV2Identity")
attributesForm(formCode: String! @doc(description: "Form code.")): AttributesFormOutput! @resolver(class: "Magento\\EavGraphQl\\Model\\Resolver\\AttributesForm") @doc(description: "Retrieve EAV attributes associated to a frontend form.")
attributesForm(formCode: String! @doc(description: "Form code.")): AttributesFormOutput!
@resolver(class: "Magento\\EavGraphQl\\Model\\Resolver\\AttributesForm")
@doc(description: "Retrieve EAV attributes associated to a frontend form.")
@cache(cacheIdentity: "Magento\\Eav\\Model\\Cache\\AttributesFormIdentity")
attributesList(entityType: AttributeEntityTypeEnum! @doc(description: "Entity type.")):
AttributesMetadataOutput
@resolver(class: "Magento\\EavGraphQl\\Model\\Resolver\\AttributesList")
Expand Down
Loading

0 comments on commit a796656

Please sign in to comment.