Skip to content

Commit c1e136b

Browse files
ENGCOM-7929: Avoids endless loop of indexers being marked as invalid #29196
2 parents efc52ed + 2b99ec4 commit c1e136b

File tree

5 files changed

+355
-89
lines changed

5 files changed

+355
-89
lines changed

app/code/Magento/Indexer/Console/Command/IndexerReindexCommand.php

Lines changed: 27 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Magento\Indexer\Console\Command;
88

9+
use Magento\Framework\App\ObjectManager;
910
use Magento\Framework\App\ObjectManagerFactory;
1011
use Magento\Framework\Console\Cli;
1112
use Magento\Framework\Exception\LocalizedException;
@@ -14,11 +15,13 @@
1415
use Magento\Framework\Indexer\IndexerInterface;
1516
use Magento\Framework\Indexer\IndexerRegistry;
1617
use Magento\Framework\Indexer\StateInterface;
18+
use Magento\Indexer\Model\Processor\MakeSharedIndexValid;
1719
use Symfony\Component\Console\Input\InputInterface;
1820
use Symfony\Component\Console\Output\OutputInterface;
1921

2022
/**
2123
* Command to run indexers
24+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2225
*/
2326
class IndexerReindexCommand extends AbstractIndexerManageCommand
2427
{
@@ -42,18 +45,26 @@ class IndexerReindexCommand extends AbstractIndexerManageCommand
4245
*/
4346
private $dependencyInfoProvider;
4447

48+
/**
49+
* @var MakeSharedIndexValid|null
50+
*/
51+
private $makeSharedValid;
52+
4553
/**
4654
* @param ObjectManagerFactory $objectManagerFactory
4755
* @param IndexerRegistry|null $indexerRegistry
4856
* @param DependencyInfoProvider|null $dependencyInfoProvider
57+
* @param MakeSharedIndexValid|null $makeSharedValid
4958
*/
5059
public function __construct(
5160
ObjectManagerFactory $objectManagerFactory,
5261
IndexerRegistry $indexerRegistry = null,
53-
DependencyInfoProvider $dependencyInfoProvider = null
62+
DependencyInfoProvider $dependencyInfoProvider = null,
63+
MakeSharedIndexValid $makeSharedValid = null
5464
) {
5565
$this->indexerRegistry = $indexerRegistry;
5666
$this->dependencyInfoProvider = $dependencyInfoProvider;
67+
$this->makeSharedValid = $makeSharedValid;
5768
parent::__construct($objectManagerFactory);
5869
}
5970

@@ -88,8 +99,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
8899
// Skip indexers having shared index that was already complete
89100
if (!in_array($sharedIndex, $this->sharedIndexesComplete)) {
90101
$indexer->reindexAll();
91-
if ($sharedIndex) {
92-
$this->validateSharedIndex($sharedIndex);
102+
if (!empty($sharedIndex) && $this->getMakeSharedValid()->execute($sharedIndex)) {
103+
$this->sharedIndexesComplete[] = $sharedIndex;
93104
}
94105
}
95106
$resultTime = microtime(true) - $startTime;
@@ -215,54 +226,6 @@ private function validateIndexerStatus(IndexerInterface $indexer)
215226
}
216227
}
217228

218-
/**
219-
* Get indexer ids that have common shared index
220-
*
221-
* @param string $sharedIndex
222-
* @return array
223-
*/
224-
private function getIndexerIdsBySharedIndex($sharedIndex)
225-
{
226-
$indexers = $this->getConfig()->getIndexers();
227-
$result = [];
228-
foreach ($indexers as $indexerConfig) {
229-
if ($indexerConfig['shared_index'] == $sharedIndex) {
230-
$result[] = $indexerConfig['indexer_id'];
231-
}
232-
}
233-
return $result;
234-
}
235-
236-
/**
237-
* Validate indexers by shared index ID
238-
*
239-
* @param string $sharedIndex
240-
* @return $this
241-
*/
242-
private function validateSharedIndex($sharedIndex)
243-
{
244-
if (empty($sharedIndex)) {
245-
throw new \InvalidArgumentException(
246-
'The sharedIndex is an invalid shared index identifier. Verify the identifier and try again.'
247-
);
248-
}
249-
$indexerIds = $this->getIndexerIdsBySharedIndex($sharedIndex);
250-
if (empty($indexerIds)) {
251-
return $this;
252-
}
253-
foreach ($indexerIds as $indexerId) {
254-
$indexer = $this->getIndexerRegistry()->get($indexerId);
255-
/** @var \Magento\Indexer\Model\Indexer\State $state */
256-
$state = $indexer->getState();
257-
$state->setStatus(StateInterface::STATUS_WORKING);
258-
$state->save();
259-
$state->setStatus(StateInterface::STATUS_VALID);
260-
$state->save();
261-
}
262-
$this->sharedIndexesComplete[] = $sharedIndex;
263-
return $this;
264-
}
265-
266229
/**
267230
* Get config
268231
*
@@ -278,30 +241,30 @@ private function getConfig()
278241
}
279242

280243
/**
281-
* Get indexer registry
244+
* Get dependency info provider
282245
*
283-
* @return IndexerRegistry
246+
* @return DependencyInfoProvider
284247
* @deprecated 100.2.0
285248
*/
286-
private function getIndexerRegistry()
249+
private function getDependencyInfoProvider()
287250
{
288-
if (!$this->indexerRegistry) {
289-
$this->indexerRegistry = $this->getObjectManager()->get(IndexerRegistry::class);
251+
if (!$this->dependencyInfoProvider) {
252+
$this->dependencyInfoProvider = $this->getObjectManager()->get(DependencyInfoProvider::class);
290253
}
291-
return $this->indexerRegistry;
254+
return $this->dependencyInfoProvider;
292255
}
293256

294257
/**
295-
* Get dependency info provider
258+
* Get MakeSharedIndexValid processor.
296259
*
297-
* @return DependencyInfoProvider
298-
* @deprecated 100.2.0
260+
* @return MakeSharedIndexValid
299261
*/
300-
private function getDependencyInfoProvider()
262+
private function getMakeSharedValid(): MakeSharedIndexValid
301263
{
302-
if (!$this->dependencyInfoProvider) {
303-
$this->dependencyInfoProvider = $this->getObjectManager()->get(DependencyInfoProvider::class);
264+
if (!$this->makeSharedValid) {
265+
$this->makeSharedValid = $this->getObjectManager()->get(MakeSharedIndexValid::class);
304266
}
305-
return $this->dependencyInfoProvider;
267+
268+
return $this->makeSharedValid;
306269
}
307270
}

app/code/Magento/Indexer/Model/Processor.php

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,23 @@
55
*/
66
namespace Magento\Indexer\Model;
77

8+
use Magento\Framework\App\ObjectManager;
89
use Magento\Framework\Indexer\ConfigInterface;
910
use Magento\Framework\Indexer\IndexerInterface;
1011
use Magento\Framework\Indexer\IndexerInterfaceFactory;
11-
use Magento\Framework\Indexer\StateInterface;
12+
use Magento\Framework\Mview\ProcessorInterface;
13+
use Magento\Indexer\Model\Processor\MakeSharedIndexValid;
1214

1315
/**
1416
* Indexer processor
1517
*/
1618
class Processor
1719
{
20+
/**
21+
* @var array
22+
*/
23+
private $sharedIndexesComplete = [];
24+
1825
/**
1926
* @var ConfigInterface
2027
*/
@@ -31,26 +38,34 @@ class Processor
3138
protected $indexersFactory;
3239

3340
/**
34-
* @var \Magento\Framework\Mview\ProcessorInterface
41+
* @var ProcessorInterface
3542
*/
3643
protected $mviewProcessor;
3744

45+
/**
46+
* @var MakeSharedIndexValid
47+
*/
48+
protected $makeSharedValid;
49+
3850
/**
3951
* @param ConfigInterface $config
4052
* @param IndexerInterfaceFactory $indexerFactory
4153
* @param Indexer\CollectionFactory $indexersFactory
42-
* @param \Magento\Framework\Mview\ProcessorInterface $mviewProcessor
54+
* @param ProcessorInterface $mviewProcessor
55+
* @param MakeSharedIndexValid|null $makeSharedValid
4356
*/
4457
public function __construct(
4558
ConfigInterface $config,
4659
IndexerInterfaceFactory $indexerFactory,
4760
Indexer\CollectionFactory $indexersFactory,
48-
\Magento\Framework\Mview\ProcessorInterface $mviewProcessor
61+
ProcessorInterface $mviewProcessor,
62+
MakeSharedIndexValid $makeSharedValid = null
4963
) {
5064
$this->config = $config;
5165
$this->indexerFactory = $indexerFactory;
5266
$this->indexersFactory = $indexersFactory;
5367
$this->mviewProcessor = $mviewProcessor;
68+
$this->makeSharedValid = $makeSharedValid ?: ObjectManager::getInstance()->get(MakeSharedIndexValid::class);
5469
}
5570

5671
/**
@@ -60,27 +75,21 @@ public function __construct(
6075
*/
6176
public function reindexAllInvalid()
6277
{
63-
$sharedIndexesComplete = [];
6478
foreach (array_keys($this->config->getIndexers()) as $indexerId) {
6579
/** @var Indexer $indexer */
6680
$indexer = $this->indexerFactory->create();
6781
$indexer->load($indexerId);
6882
$indexerConfig = $this->config->getIndexer($indexerId);
83+
6984
if ($indexer->isInvalid()) {
7085
// Skip indexers having shared index that was already complete
7186
$sharedIndex = $indexerConfig['shared_index'] ?? null;
72-
if (!in_array($sharedIndex, $sharedIndexesComplete)) {
87+
if (!in_array($sharedIndex, $this->sharedIndexesComplete)) {
7388
$indexer->reindexAll();
74-
} else {
75-
/** @var \Magento\Indexer\Model\Indexer\State $state */
76-
$state = $indexer->getState();
77-
$state->setStatus(StateInterface::STATUS_WORKING);
78-
$state->save();
79-
$state->setStatus(StateInterface::STATUS_VALID);
80-
$state->save();
81-
}
82-
if ($sharedIndex) {
83-
$sharedIndexesComplete[] = $sharedIndex;
89+
90+
if (!empty($sharedIndex) && $this->makeSharedValid->execute($sharedIndex)) {
91+
$this->sharedIndexesComplete[] = $sharedIndex;
92+
}
8493
}
8594
}
8695
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Indexer\Model\Processor;
10+
11+
use Magento\Framework\Indexer\ConfigInterface;
12+
use Magento\Framework\Indexer\IndexerRegistry;
13+
use Magento\Framework\Indexer\StateInterface;
14+
use Magento\Indexer\Model\Indexer\State;
15+
16+
/**
17+
* Class processor makes indexers valid by shared index ID
18+
*/
19+
class MakeSharedIndexValid
20+
{
21+
/**
22+
* @var ConfigInterface
23+
*/
24+
private $config;
25+
26+
/**
27+
* @var IndexerRegistry
28+
*/
29+
private $indexerRegistry;
30+
31+
/**
32+
* ValidateSharedIndex constructor.
33+
*
34+
* @param ConfigInterface $config
35+
* @param IndexerRegistry $indexerRegistry
36+
*/
37+
public function __construct(ConfigInterface $config, IndexerRegistry $indexerRegistry)
38+
{
39+
$this->config = $config;
40+
$this->indexerRegistry = $indexerRegistry;
41+
}
42+
43+
/**
44+
* Validate indexers by shared index ID
45+
*
46+
* @param string $sharedIndex
47+
* @return bool
48+
* @throws \Exception
49+
*/
50+
public function execute(string $sharedIndex): bool
51+
{
52+
if (empty($sharedIndex)) {
53+
throw new \InvalidArgumentException(
54+
"The '{$sharedIndex}' is an invalid shared index identifier. Verify the identifier and try again.",
55+
);
56+
}
57+
58+
$indexerIds = $this->getIndexerIdsBySharedIndex($sharedIndex);
59+
if (empty($indexerIds)) {
60+
return false;
61+
}
62+
63+
foreach ($indexerIds as $indexerId) {
64+
$indexer = $this->indexerRegistry->get($indexerId);
65+
/** @var State $state */
66+
$state = $indexer->getState();
67+
$state->setStatus(StateInterface::STATUS_WORKING);
68+
$state->save();
69+
$state->setStatus(StateInterface::STATUS_VALID);
70+
$state->save();
71+
}
72+
73+
return true;
74+
}
75+
76+
/**
77+
* Get indexer ids that have common shared index
78+
*
79+
* @param string $sharedIndex
80+
* @return array
81+
*/
82+
private function getIndexerIdsBySharedIndex(string $sharedIndex): array
83+
{
84+
$indexers = $this->config->getIndexers();
85+
86+
$result = [];
87+
foreach ($indexers as $indexerConfig) {
88+
if ($indexerConfig['shared_index'] == $sharedIndex) {
89+
$result[] = $indexerConfig['indexer_id'];
90+
}
91+
}
92+
93+
return $result;
94+
}
95+
}

0 commit comments

Comments
 (0)