Skip to content

Commit 6b5de07

Browse files
author
Yaroslav Onischenko
committed
MAGETWO-66344: [Performance] Bump in stock SQL queries
2 parents 0aa0031 + daba1ec commit 6b5de07

File tree

2 files changed

+57
-45
lines changed

2 files changed

+57
-45
lines changed

app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProvider.php

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ class LowestPriceOptionsProvider implements LowestPriceOptionsProviderInterface
3030
*/
3131
private $collectionFactory;
3232

33+
/**
34+
* Key is product id. Value is array of prepared linked products
35+
*
36+
* @var array
37+
*/
38+
private $linkedProductMap;
39+
3340
/**
3441
* @param ResourceConnection $resourceConnection
3542
* @param LinkedProductSelectBuilderInterface $linkedProductSelectBuilder
@@ -50,14 +57,16 @@ public function __construct(
5057
*/
5158
public function getProducts(ProductInterface $product)
5259
{
53-
$productIds = $this->resource->getConnection()->fetchCol(
54-
'(' . implode(') UNION (', $this->linkedProductSelectBuilder->build($product->getId())) . ')'
55-
);
56-
57-
$lowestPriceChildProducts = $this->collectionFactory->create()
58-
->addAttributeToSelect(['price', 'special_price'])
59-
->addIdFilter($productIds)
60-
->getItems();
61-
return $lowestPriceChildProducts;
60+
if (!isset($this->linkedProductMap[$product->getId()])) {
61+
$productIds = $this->resource->getConnection()->fetchCol(
62+
'(' . implode(') UNION (', $this->linkedProductSelectBuilder->build($product->getId())) . ')'
63+
);
64+
65+
$this->linkedProductMap[$product->getId()] = $this->collectionFactory->create()
66+
->addAttributeToSelect(['price', 'special_price'])
67+
->addIdFilter($productIds)
68+
->getItems();
69+
}
70+
return $this->linkedProductMap[$product->getId()];
6271
}
6372
}

dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ class LowestPriceOptionProviderTest extends \PHPUnit_Framework_TestCase
1818
*/
1919
private $storeManager;
2020

21-
/**
22-
* @var LowestPriceOptionsProviderInterface
23-
*/
24-
private $lowestPriceOptionsProvider;
25-
2621
/**
2722
* @var ProductRepositoryInterface
2823
*/
@@ -32,21 +27,18 @@ protected function setUp()
3227
{
3328
$this->storeManager = Bootstrap::getObjectManager()->get(StoreManagerInterface::class);
3429
$this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class);
35-
$this->lowestPriceOptionsProvider = Bootstrap::getObjectManager()->get(
36-
LowestPriceOptionsProviderInterface::class
37-
);
3830
}
3931

4032
/**
4133
* @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
4234
*/
4335
public function testGetProductsIfOneOfChildIsDisabled()
4436
{
45-
$configurableProduct = $this->productRepository->getById(1, false, null, true);
46-
$lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct);
47-
$this->assertCount(1, $lowestPriceChildrenProducts);
37+
$configurableProduct = $this->productRepository->get('configurable', false, null, true);
38+
$lowestPriceChildrenProducts = $this->createLowestPriceOptionsProvider()->getProducts($configurableProduct);
39+
self::assertCount(1, $lowestPriceChildrenProducts);
4840
$lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts);
49-
$this->assertEquals(10, $lowestPriceChildrenProduct->getPrice());
41+
self::assertEquals(10, $lowestPriceChildrenProduct->getPrice());
5042

5143
// load full aggregation root
5244
$lowestPriceChildProduct = $this->productRepository->get(
@@ -62,22 +54,22 @@ public function testGetProductsIfOneOfChildIsDisabled()
6254
$this->productRepository->save($lowestPriceChildProduct);
6355
$this->storeManager->setCurrentStore($currentStoreId);
6456

65-
$lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct);
66-
$this->assertCount(1, $lowestPriceChildrenProducts);
57+
$lowestPriceChildrenProducts = $this->createLowestPriceOptionsProvider()->getProducts($configurableProduct);
58+
self::assertCount(1, $lowestPriceChildrenProducts);
6759
$lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts);
68-
$this->assertEquals(20, $lowestPriceChildrenProduct->getPrice());
60+
self::assertEquals(20, $lowestPriceChildrenProduct->getPrice());
6961
}
7062

7163
/**
7264
* @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
7365
*/
7466
public function testGetProductsIfOneOfChildIsDisabledPerStore()
7567
{
76-
$configurableProduct = $this->productRepository->getById(1, false, null, true);
77-
$lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct);
78-
$this->assertCount(1, $lowestPriceChildrenProducts);
68+
$configurableProduct = $this->productRepository->get('configurable', false, null, true);
69+
$lowestPriceChildrenProducts = $this->createLowestPriceOptionsProvider()->getProducts($configurableProduct);
70+
self::assertCount(1, $lowestPriceChildrenProducts);
7971
$lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts);
80-
$this->assertEquals(10, $lowestPriceChildrenProduct->getPrice());
72+
self::assertEquals(10, $lowestPriceChildrenProduct->getPrice());
8173

8274
// load full aggregation root
8375
$lowestPriceChildProduct = $this->productRepository->get(
@@ -94,22 +86,22 @@ public function testGetProductsIfOneOfChildIsDisabledPerStore()
9486
$this->productRepository->save($lowestPriceChildProduct);
9587
$this->storeManager->setCurrentStore($currentStoreId);
9688

97-
$lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct);
98-
$this->assertCount(1, $lowestPriceChildrenProducts);
89+
$lowestPriceChildrenProducts = $this->createLowestPriceOptionsProvider()->getProducts($configurableProduct);
90+
self::assertCount(1, $lowestPriceChildrenProducts);
9991
$lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts);
100-
$this->assertEquals(20, $lowestPriceChildrenProduct->getPrice());
92+
self::assertEquals(20, $lowestPriceChildrenProduct->getPrice());
10193
}
10294

10395
/**
10496
* @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
10597
*/
10698
public function testGetProductsIfOneOfChildIsOutOfStock()
10799
{
108-
$configurableProduct = $this->productRepository->getById(1, false, null, true);
109-
$lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct);
110-
$this->assertCount(1, $lowestPriceChildrenProducts);
100+
$configurableProduct = $this->productRepository->get('configurable', false, null, true);
101+
$lowestPriceChildrenProducts = $this->createLowestPriceOptionsProvider()->getProducts($configurableProduct);
102+
self::assertCount(1, $lowestPriceChildrenProducts);
111103
$lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts);
112-
$this->assertEquals(10, $lowestPriceChildrenProduct->getPrice());
104+
self::assertEquals(10, $lowestPriceChildrenProduct->getPrice());
113105

114106
// load full aggregation root
115107
$lowestPriceChildProduct = $this->productRepository->get(
@@ -121,11 +113,10 @@ public function testGetProductsIfOneOfChildIsOutOfStock()
121113
$stockItem = $lowestPriceChildProduct->getExtensionAttributes()->getStockItem();
122114
$stockItem->setIsInStock(0);
123115
$this->productRepository->save($lowestPriceChildProduct);
124-
125-
$lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct);
126-
$this->assertCount(1, $lowestPriceChildrenProducts);
116+
$lowestPriceChildrenProducts = $this->createLowestPriceOptionsProvider()->getProducts($configurableProduct);
117+
self::assertCount(1, $lowestPriceChildrenProducts);
127118
$lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts);
128-
$this->assertEquals(20, $lowestPriceChildrenProduct->getPrice());
119+
self::assertEquals(20, $lowestPriceChildrenProduct->getPrice());
129120
}
130121

131122
/**
@@ -135,10 +126,10 @@ public function testGetProductsIfOneOfChildIsOutOfStock()
135126
public function testGetProductsIfOneOfChildrenIsAssignedToOtherWebsite()
136127
{
137128
$configurableProduct = $this->productRepository->getById(1, false, null, true);
138-
$lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct);
139-
$this->assertCount(1, $lowestPriceChildrenProducts);
129+
$lowestPriceChildrenProducts = $this->createLowestPriceOptionsProvider()->getProducts($configurableProduct);
130+
self::assertCount(1, $lowestPriceChildrenProducts);
140131
$lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts);
141-
$this->assertEquals(10, $lowestPriceChildrenProduct->getPrice());
132+
self::assertEquals(10, $lowestPriceChildrenProduct->getPrice());
142133

143134
/** @var \Magento\Store\Api\WebsiteRepositoryInterface $webSiteRepository */
144135
$webSiteRepository = Bootstrap::getObjectManager()->get(\Magento\Store\Api\WebsiteRepositoryInterface::class);
@@ -150,9 +141,21 @@ public function testGetProductsIfOneOfChildrenIsAssignedToOtherWebsite()
150141
$lowestPriceChildrenProduct->setExtensionAttributes($attributes);
151142
$this->productRepository->save($lowestPriceChildrenProduct);
152143

153-
$lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct);
154-
$this->assertCount(1, $lowestPriceChildrenProducts);
144+
$lowestPriceChildrenProducts = $this->createLowestPriceOptionsProvider()->getProducts($configurableProduct);
145+
self::assertCount(1, $lowestPriceChildrenProducts);
155146
$lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts);
156-
$this->assertEquals(20, $lowestPriceChildrenProduct->getPrice());
147+
self::assertEquals(20, $lowestPriceChildrenProduct->getPrice());
148+
}
149+
150+
/**
151+
* As LowestPriceOptionsProviderInterface used multiple times in scope
152+
* of one test we need to always recreate it and prevent internal caching in property
153+
* @return LowestPriceOptionsProviderInterface
154+
*/
155+
private function createLowestPriceOptionsProvider()
156+
{
157+
return Bootstrap::getObjectManager()->create(
158+
LowestPriceOptionsProviderInterface::class
159+
);
157160
}
158161
}

0 commit comments

Comments
 (0)