Skip to content

Commit 92c0dff

Browse files
committed
ACP2E-4303: Reindexing stuck due to high memory usage
1 parent c009634 commit 92c0dff

File tree

3 files changed

+87
-22
lines changed

3 files changed

+87
-22
lines changed

app/code/Magento/CatalogRule/Model/Rule.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,8 @@ public function getMatchingProductIds()
401401
$this->cachedWebsitesMap = $this->_getWebsitesMap();
402402
$websiteIds = $this->getWebsiteIds();
403403
$this->cachedWebsiteIdsArray = is_array($websiteIds) ? $websiteIds : explode(',', $websiteIds);
404-
$this->cachedConditions = $this->getConditions(); $this->_resourceIterator->walk(
404+
$this->cachedConditions = $this->getConditions();
405+
$this->_resourceIterator->walk(
405406
$productCollection->getSelect(),
406407
[[$this, 'callbackValidateProduct']],
407408
[

app/code/Magento/CatalogRuleConfigurable/Plugin/CatalogRule/Model/Rule/ConfigurableProductHandler.php

Lines changed: 84 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace Magento\CatalogRuleConfigurable\Plugin\CatalogRule\Model\Rule;
99

10+
use Magento\CatalogRule\Model\Rule;
1011
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable as ConfigurableProductsResourceModel;
1112
use Magento\Framework\App\ResourceConnection;
1213

@@ -50,37 +51,104 @@ public function __construct(
5051
/**
5152
* Match configurable child products if configurable product matches the condition
5253
*
53-
* @param \Magento\CatalogRule\Model\Rule $rule
54+
* @param Rule $rule
5455
* @param \Closure $proceed
5556
* @return array
5657
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
57-
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
5858
*/
5959
public function aroundGetMatchingProductIds(
60-
\Magento\CatalogRule\Model\Rule $rule,
60+
Rule $rule,
6161
\Closure $proceed
6262
): array {
6363
$productsFilter = $rule->getProductsFilter() ? (array) $rule->getProductsFilter() : [];
64-
if ($productsFilter) {
65-
$parentIds = $this->configurable->getParentIdsByChild($productsFilter);
66-
if ($parentIds) {
67-
$rule->setProductsFilter(
68-
array_unique(
69-
array_merge(
70-
$productsFilter,
71-
$parentIds
72-
)
73-
)
74-
);
75-
}
76-
}
64+
65+
$this->updateProductsFilter($rule, $productsFilter);
7766

7867
$productIds = $proceed();
7968

8069
if (self::$allConfigurableProductIds === null) {
8170
self::$allConfigurableProductIds = $this->loadAllConfigurableProductIds();
8271
}
8372

73+
return $this->processConfigurableProducts($productIds, $productsFilter);
74+
}
75+
76+
/**
77+
* Update products filter to include parent IDs and remove duplicate children
78+
*
79+
* @param Rule $rule
80+
* @param array $productsFilter
81+
* @return void
82+
*/
83+
private function updateProductsFilter(
84+
Rule $rule,
85+
array $productsFilter
86+
): void {
87+
if (!$productsFilter) {
88+
return;
89+
}
90+
91+
$parentIds = $this->configurable->getParentIdsByChild($productsFilter);
92+
if (!$parentIds) {
93+
return;
94+
}
95+
96+
$childrenToRemove = $this->getChildrenToRemove($productsFilter, $parentIds);
97+
$filteredProducts = array_diff($productsFilter, $childrenToRemove);
98+
99+
$rule->setProductsFilter(
100+
array_unique(
101+
array_merge(
102+
$filteredProducts,
103+
$parentIds
104+
)
105+
)
106+
);
107+
}
108+
109+
/**
110+
* Get children to remove from filter to avoid redundancy
111+
*
112+
* @param array $productsFilter
113+
* @param array $parentIds
114+
* @return array
115+
*/
116+
private function getChildrenToRemove(array $productsFilter, array $parentIds): array
117+
{
118+
$childrenToRemove = [];
119+
120+
foreach ($parentIds as $parentId) {
121+
if (in_array($parentId, $productsFilter)) {
122+
continue;
123+
}
124+
125+
if (!isset(self::$childrenProducts[$parentId])) {
126+
self::$childrenProducts[$parentId] = $this->configurable->getChildrenIds($parentId)[0];
127+
}
128+
$children = self::$childrenProducts[$parentId];
129+
130+
$childrenInFilter = array_intersect($productsFilter, $children);
131+
if (count($childrenInFilter) > 1) {
132+
$childrenInFilterArray = array_values($childrenInFilter);
133+
$childrenCount = count($childrenInFilterArray);
134+
for ($i = 1; $i < $childrenCount; $i++) {
135+
$childrenToRemove[] = $childrenInFilterArray[$i];
136+
}
137+
}
138+
}
139+
140+
return $childrenToRemove;
141+
}
142+
143+
/**
144+
* Process configurable products and apply parent validation to children
145+
*
146+
* @param array $productIds
147+
* @param array $productsFilter
148+
* @return array
149+
*/
150+
private function processConfigurableProducts(array $productIds, array $productsFilter): array
151+
{
84152
foreach (array_keys($productIds) as $productId) {
85153
if (isset(self::$allConfigurableProductIds[$productId])) {
86154
if (!isset(self::$childrenProducts[$productId])) {

app/code/Magento/CatalogRuleConfigurable/Test/Unit/Plugin/CatalogRule/Model/Rule/ConfigurableProductHandlerTest.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ protected function setUp(): void
6363
$this->selectMock = $this->createMock(Select::class);
6464
$this->ruleMock = $this->createMock(Rule::class);
6565

66-
// Set up default resource connection behavior
6766
$this->resourceConnectionMock->method('getConnection')
6867
->willReturn($this->connectionMock);
6968
$this->resourceConnectionMock->method('getTableName')
@@ -74,7 +73,6 @@ protected function setUp(): void
7473
$this->resourceConnectionMock
7574
);
7675

77-
// Reset static properties between tests
7876
$this->resetStaticProperties();
7977
}
8078

@@ -88,11 +86,9 @@ private function resetStaticProperties(): void
8886
$reflection = new \ReflectionClass(ConfigurableProductHandler::class);
8987

9088
$allConfigurableProductIdsProperty = $reflection->getProperty('allConfigurableProductIds');
91-
$allConfigurableProductIdsProperty->setAccessible(true);
9289
$allConfigurableProductIdsProperty->setValue(null, null);
9390

9491
$childrenProductsProperty = $reflection->getProperty('childrenProducts');
95-
$childrenProductsProperty->setAccessible(true);
9692
$childrenProductsProperty->setValue(null, []);
9793
}
9894

@@ -273,7 +269,7 @@ public static function aroundGetMatchingProductIdsDataProvider(): array
273269
],
274270
[
275271
['simple11', 'simple12',],
276-
['simple11', 'simple12', 'conf1',],
272+
['simple11', 'conf1',],
277273
['simple11' => [1 => false], 'conf1' => [1 => true],],
278274
['simple11' => [1 => true], 'simple12' => [1 => true],],
279275
],

0 commit comments

Comments
 (0)