Skip to content

Commit 6b91873

Browse files
committed
Merge branch 'ACP2E-1875' of https://github.com/magento-l3/magento2ce into L3-PR-2023-06-23
2 parents 8d79a4c + 723d3f5 commit 6b91873

File tree

13 files changed

+429
-17
lines changed

13 files changed

+429
-17
lines changed

app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Magento\CatalogSearch\Model\ResourceModel\Fulltext as FulltextResource;
1313
use Magento\Framework\App\ObjectManager;
1414
use Magento\Framework\Indexer\DimensionProviderInterface;
15+
use Magento\Framework\Indexer\SaveHandler\StackedActionsIndexerInterface;
1516
use Magento\Framework\Indexer\SaveHandler\IndexerInterface;
1617
use Magento\Store\Model\StoreDimensionProvider;
1718
use Magento\Indexer\Model\ProcessManager;
@@ -40,6 +41,13 @@ class Fulltext implements
4041
*/
4142
private const BATCH_SIZE = 1000;
4243

44+
/**
45+
* Deployment config path
46+
*
47+
* @var string
48+
*/
49+
private const DEPLOYMENT_CONFIG_INDEXER_BATCHES = 'indexer/batch_size/';
50+
4351
/**
4452
* @var array index structure
4553
*/
@@ -94,13 +102,6 @@ class Fulltext implements
94102
*/
95103
private $deploymentConfig;
96104

97-
/**
98-
* Deployment config path
99-
*
100-
* @var string
101-
*/
102-
private const DEPLOYMENT_CONFIG_INDEXER_BATCHES = 'indexer/batch_size/';
103-
104105
/**
105106
* @param FullFactory $fullActionFactory
106107
* @param IndexerHandlerFactory $indexerHandlerFactory
@@ -156,7 +157,7 @@ public function execute($entityIds)
156157
/**
157158
* @inheritdoc
158159
*
159-
* @throws \InvalidArgumentException
160+
* @throws \InvalidArgumentException|\Exception
160161
* @since 101.0.0
161162
*/
162163
public function executeByDimensions(array $dimensions, \Traversable $entityIds = null)
@@ -206,6 +207,7 @@ public function executeByDimensions(array $dimensions, \Traversable $entityIds =
206207
* @param IndexerInterface $saveHandler
207208
* @param array $dimensions
208209
* @param array $entityIds
210+
* @throws \Exception
209211
*/
210212
private function processBatch(
211213
IndexerInterface $saveHandler,
@@ -216,9 +218,24 @@ private function processBatch(
216218
$productIds = array_unique(
217219
array_merge($entityIds, $this->fulltextResource->getRelationsByChild($entityIds))
218220
);
221+
219222
if ($saveHandler->isAvailable($dimensions)) {
220-
$saveHandler->deleteIndex($dimensions, new \ArrayIterator($productIds));
221-
$saveHandler->saveIndex($dimensions, $this->fullAction->rebuildStoreIndex($storeId, $productIds));
223+
if (in_array(StackedActionsIndexerInterface::class, class_implements($saveHandler))) {
224+
try {
225+
$saveHandler->enableStackedActions();
226+
$saveHandler->deleteIndex($dimensions, new \ArrayIterator($productIds));
227+
$saveHandler->saveIndex($dimensions, $this->fullAction->rebuildStoreIndex($storeId, $productIds));
228+
$saveHandler->triggerStackedActions();
229+
$saveHandler->disableStackedActions();
230+
} catch (\Throwable $exception) {
231+
$saveHandler->disableStackedActions();
232+
$saveHandler->deleteIndex($dimensions, new \ArrayIterator($productIds));
233+
$saveHandler->saveIndex($dimensions, $this->fullAction->rebuildStoreIndex($storeId, $productIds));
234+
}
235+
} else {
236+
$saveHandler->deleteIndex($dimensions, new \ArrayIterator($productIds));
237+
$saveHandler->saveIndex($dimensions, $this->fullAction->rebuildStoreIndex($storeId, $productIds));
238+
}
222239
}
223240
}
224241

app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/FulltextTest.php

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\CatalogSearch\Model\Indexer\Fulltext;
1111
use Magento\CatalogSearch\Model\Indexer\Fulltext\Action\Full;
1212
use Magento\CatalogSearch\Model\Indexer\Fulltext\Action\FullFactory;
13+
use Magento\Elasticsearch\Model\Indexer\IndexerHandler;
1314
use Magento\Framework\Indexer\SaveHandler\IndexerInterface;
1415
use Magento\CatalogSearch\Model\Indexer\IndexerHandlerFactory;
1516
use Magento\CatalogSearch\Model\Indexer\Scope\State;
@@ -64,7 +65,7 @@ protected function setUp(): void
6465
['create']
6566
);
6667
$fullActionFactory->expects($this->any())->method('create')->willReturn($this->fullAction);
67-
$this->saveHandler = $this->getClassMock(IndexerInterface::class);
68+
$this->saveHandler = $this->getClassMock(IndexerHandler::class);
6869
$indexerHandlerFactory = $this->createPartialMock(
6970
IndexerHandlerFactory::class,
7071
['create']
@@ -116,6 +117,9 @@ public function testExecute()
116117
$this->fulltextResource->expects($this->exactly(2))
117118
->method('getRelationsByChild')
118119
->willReturn($ids);
120+
$this->saveHandler->expects($this->exactly(count($stores)))->method('enableStackedActions');
121+
$this->saveHandler->expects($this->exactly(count($stores)))->method('triggerStackedActions');
122+
$this->saveHandler->expects($this->exactly(count($stores)))->method('disableStackedActions');
119123
$this->saveHandler->expects($this->exactly(count($stores)))->method('deleteIndex');
120124
$this->saveHandler->expects($this->exactly(2))->method('saveIndex');
121125
$this->saveHandler->expects($this->exactly(2))->method('isAvailable')->willReturn(true);
@@ -133,6 +137,40 @@ function ($store) use ($ids) {
133137
$this->model->execute($ids);
134138
}
135139

140+
public function testExecuteWithStackedQueriesException()
141+
{
142+
$ids = [1, 2, 3];
143+
$stores = [0 => 'Store 1'];
144+
$this->setupDataProvider($stores);
145+
146+
$indexData = new \ArrayObject([]);
147+
$this->fulltextResource->expects($this->exactly(1))
148+
->method('getRelationsByChild')
149+
->willReturn($ids);
150+
$this->saveHandler->expects($this->exactly(count($stores)))->method('enableStackedActions');
151+
$this->saveHandler->expects($this->exactly(count($stores) + 1))->method('deleteIndex');
152+
$this->saveHandler->expects($this->exactly(count($stores) + 1))->method('saveIndex');
153+
$this->saveHandler->expects($this->exactly(count($stores)))
154+
->method('triggerStackedActions')
155+
->willThrowException(new \Exception('error'));
156+
$this->saveHandler->expects($this->exactly(count($stores)))->method('disableStackedActions');
157+
158+
$this->saveHandler->expects($this->exactly(2))->method('saveIndex');
159+
$this->saveHandler->expects($this->exactly(1))->method('isAvailable')->willReturn(true);
160+
$consecutiveStoreRebuildArguments = array_map(
161+
function ($store) use ($ids) {
162+
return [$store, $ids];
163+
},
164+
$stores
165+
);
166+
$this->fullAction->expects($this->exactly(2))
167+
->method('rebuildStoreIndex')
168+
->withConsecutive(...$consecutiveStoreRebuildArguments)
169+
->willReturn(new \ArrayObject([$indexData, $indexData]));
170+
171+
$this->model->execute($ids);
172+
}
173+
136174
/**
137175
* @param $stores
138176
*/

app/code/Magento/Elasticsearch/Model/Adapter/Elasticsearch.php

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
use Elasticsearch\Common\Exceptions\Missing404Exception;
1010
use Exception;
11+
use LogicException;
1112
use Magento\AdvancedSearch\Model\Client\ClientInterface;
1213
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
1314
use Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\FieldProvider\StaticField;
@@ -124,6 +125,16 @@ class Elasticsearch
124125
'elasticsearchMissing404' => Missing404Exception::class
125126
];
126127

128+
/**
129+
* @var bool
130+
*/
131+
private bool $isStackQueries = false;
132+
133+
/**
134+
* @var array
135+
*/
136+
private array $stackedQueries = [];
137+
127138
/**
128139
* @param ConnectionManager $connectionManager
129140
* @param FieldMapperInterface $fieldMapper
@@ -182,6 +193,67 @@ public function __construct(
182193
}
183194
}
184195

196+
/**
197+
* Disable query stacking
198+
*
199+
* @return void
200+
*/
201+
public function disableStackQueriesMode(): void
202+
{
203+
$this->stackedQueries = [];
204+
$this->isStackQueries = false;
205+
}
206+
207+
/**
208+
* Enable query stacking
209+
*
210+
* @return void
211+
*/
212+
public function enableStackQueriesMode(): void
213+
{
214+
$this->isStackQueries = true;
215+
}
216+
217+
/**
218+
* Run the stacked queries
219+
*
220+
* @return $this
221+
* @throws Exception
222+
*/
223+
public function triggerStackedQueries(): self
224+
{
225+
try {
226+
if (!empty($this->stackedQueries)) {
227+
$this->client->bulkQuery($this->stackedQueries);
228+
}
229+
} catch (Exception $e) {
230+
$this->logger->critical($e);
231+
throw $e;
232+
}
233+
234+
return $this;
235+
}
236+
237+
/**
238+
* Combine query body request
239+
*
240+
* @param array $queries
241+
* @return void
242+
* @throws LogicException
243+
*/
244+
private function stackQueries(array $queries): void
245+
{
246+
if ($this->isStackQueries) {
247+
if (empty($this->stackedQueries)) {
248+
$this->stackedQueries = $queries;
249+
} else {
250+
$this->stackedQueries['body'] = array_merge($this->stackedQueries['body'], $queries['body']);
251+
}
252+
} else {
253+
throw new LogicException('Stacked indexer queries not enabled');
254+
}
255+
}
256+
185257
/**
186258
* Retrieve Elasticsearch server status
187259
*
@@ -234,7 +306,11 @@ public function addDocs(array $documents, $storeId, $mappedIndexerId)
234306
try {
235307
$indexName = $this->indexNameResolver->getIndexName($storeId, $mappedIndexerId, $this->preparedIndex);
236308
$bulkIndexDocuments = $this->getDocsArrayInBulkIndexFormat($documents, $indexName);
237-
$this->client->bulkQuery($bulkIndexDocuments);
309+
if ($this->isStackQueries === false) {
310+
$this->client->bulkQuery($bulkIndexDocuments);
311+
} else {
312+
$this->stackQueries($bulkIndexDocuments);
313+
}
238314
} catch (Exception $e) {
239315
$this->logger->critical($e);
240316
throw $e;
@@ -309,7 +385,11 @@ public function deleteDocs(array $documentIds, $storeId, $mappedIndexerId)
309385
$indexName,
310386
self::BULK_ACTION_DELETE
311387
);
312-
$this->client->bulkQuery($bulkDeleteDocuments);
388+
if ($this->isStackQueries === false) {
389+
$this->client->bulkQuery($bulkDeleteDocuments);
390+
} else {
391+
$this->stackQueries($bulkDeleteDocuments);
392+
}
313393
} catch (Exception $e) {
314394
$this->logger->critical($e);
315395
throw $e;

app/code/Magento/Elasticsearch/Model/Indexer/IndexerHandler.php

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,21 @@
1515
use Magento\Framework\App\ScopeResolverInterface;
1616
use Magento\Framework\Indexer\IndexStructureInterface;
1717
use Magento\Framework\Indexer\SaveHandler\Batch;
18+
use Magento\Framework\Indexer\SaveHandler\StackedActionsIndexerInterface;
1819
use Magento\Framework\Indexer\SaveHandler\IndexerInterface;
1920
use Magento\Framework\Search\Request\Dimension;
2021
use Magento\Framework\Indexer\CacheContext;
2122

2223
/**
2324
* Indexer Handler for Elasticsearch engine.
25+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2426
*/
25-
class IndexerHandler implements IndexerInterface
27+
class IndexerHandler implements IndexerInterface, StackedActionsIndexerInterface
2628
{
2729
/**
2830
* Size of default batch
2931
*/
30-
const DEFAULT_BATCH_SIZE = 500;
32+
public const DEFAULT_BATCH_SIZE = 500;
3133

3234
/**
3335
* @var IndexStructureInterface
@@ -98,6 +100,7 @@ class IndexerHandler implements IndexerInterface
98100
* @param DeploymentConfig|null $deploymentConfig
99101
* @param CacheContext|null $cacheContext
100102
* @param Processor|null $processor
103+
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
101104
*/
102105
public function __construct(
103106
IndexStructureInterface $indexStructure,
@@ -123,6 +126,37 @@ public function __construct(
123126
$this->processor = $processor ?: ObjectManager::getInstance()->get(Processor::class);
124127
}
125128

129+
/**
130+
* Disables stacked actions mode
131+
*
132+
* @return void
133+
*/
134+
public function disableStackedActions(): void
135+
{
136+
$this->adapter->disableStackQueriesMode();
137+
}
138+
139+
/**
140+
* Enables stacked actions mode
141+
*
142+
* @return void
143+
*/
144+
public function enableStackedActions(): void
145+
{
146+
$this->adapter->enableStackQueriesMode();
147+
}
148+
149+
/**
150+
* Runs stacked actions
151+
*
152+
* @return void
153+
* @throws \Exception
154+
*/
155+
public function triggerStackedActions(): void
156+
{
157+
$this->adapter->triggerStackedQueries();
158+
}
159+
126160
/**
127161
* @inheritdoc
128162
*/
@@ -181,7 +215,9 @@ public function deleteIndex($dimensions, \Traversable $documents)
181215
$scopeId = $this->scopeResolver->getScope($dimension->getValue())->getId();
182216
$documentIds = [];
183217
foreach ($documents as $document) {
184-
$documentIds[$document] = $document;
218+
if ($document) {
219+
$documentIds[$document] = $document;
220+
}
185221
}
186222
$this->adapter->deleteDocs($documentIds, $scopeId, $this->getIndexerId());
187223
return $this;

0 commit comments

Comments
 (0)