Skip to content

Commit 09bd175

Browse files
author
Volodymyr Kublytskyi
committed
MAGETWO-83503: [2.2] - Add command to view mview state and queue #12122
- Merge Pull Request #12122 from convenient/magento2:2-2-0-mview-list - Merged commits: 1. 9021561 2. 1e34fde 3. 6d3bffa 4. dede2d1 5. fa1b310 6. f4857ec 7. c80710a 8. 63ec3f7 9. d3d300b 10. c63330f 11. 709f88a 12. 831000b 13. 62e67e1 14. 4af04b1 15. 700fe22 16. ca50c9d 17. 10df2ce 18. 3d34bc8
2 parents 9fc1138 + 3d34bc8 commit 09bd175

File tree

2 files changed

+236
-32
lines changed

2 files changed

+236
-32
lines changed

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

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

88
use Symfony\Component\Console\Input\InputInterface;
99
use Symfony\Component\Console\Output\OutputInterface;
10+
use Magento\Framework\Indexer;
11+
use Magento\Framework\Mview;
1012

1113
/**
1214
* Command for displaying status of indexers.
@@ -30,21 +32,84 @@ protected function configure()
3032
*/
3133
protected function execute(InputInterface $input, OutputInterface $output)
3234
{
35+
$table = $this->getHelperSet()->get('table');
36+
$table->setHeaders(['Title', 'Status', 'Update On', 'Schedule Status', 'Schedule Updated']);
37+
38+
$rows = [];
39+
3340
$indexers = $this->getIndexers($input);
3441
foreach ($indexers as $indexer) {
35-
$status = 'unknown';
36-
switch ($indexer->getStatus()) {
37-
case \Magento\Framework\Indexer\StateInterface::STATUS_VALID:
38-
$status = 'Ready';
39-
break;
40-
case \Magento\Framework\Indexer\StateInterface::STATUS_INVALID:
41-
$status = 'Reindex required';
42-
break;
43-
case \Magento\Framework\Indexer\StateInterface::STATUS_WORKING:
44-
$status = 'Processing';
45-
break;
42+
$view = $indexer->getView();
43+
44+
$rowData = [
45+
'Title' => $indexer->getTitle(),
46+
'Status' => $this->getStatus($indexer),
47+
'Update On' => $indexer->isScheduled() ? 'Schedule' : 'Save',
48+
'Schedule Status' => '',
49+
'Updated' => '',
50+
];
51+
52+
if ($indexer->isScheduled()) {
53+
$state = $view->getState();
54+
$rowData['Schedule Status'] = "{$state->getStatus()} ({$this->getPendingCount($view)} in backlog)";
55+
$rowData['Updated'] = $state->getUpdated();
4656
}
47-
$output->writeln(sprintf('%-50s ', $indexer->getTitle() . ':') . $status);
57+
58+
$rows[] = $rowData;
59+
}
60+
61+
usort($rows, function ($comp1, $comp2) {
62+
return strcmp($comp1['Title'], $comp2['Title']);
63+
});
64+
65+
$table->addRows($rows);
66+
$table->render($output);
67+
}
68+
69+
/**
70+
* @param Indexer\IndexerInterface $indexer
71+
* @return string
72+
*/
73+
private function getStatus(Indexer\IndexerInterface $indexer)
74+
{
75+
$status = 'unknown';
76+
switch ($indexer->getStatus()) {
77+
case \Magento\Framework\Indexer\StateInterface::STATUS_VALID:
78+
$status = 'Ready';
79+
break;
80+
case \Magento\Framework\Indexer\StateInterface::STATUS_INVALID:
81+
$status = 'Reindex required';
82+
break;
83+
case \Magento\Framework\Indexer\StateInterface::STATUS_WORKING:
84+
$status = 'Processing';
85+
break;
4886
}
87+
return $status;
88+
}
89+
90+
/**
91+
* @param Mview\ViewInterface $view
92+
* @return string
93+
*/
94+
private function getPendingCount(Mview\ViewInterface $view)
95+
{
96+
$changelog = $view->getChangelog();
97+
98+
try {
99+
$currentVersionId = $changelog->getVersion();
100+
} catch (Mview\View\ChangelogTableNotExistsException $e) {
101+
return '';
102+
}
103+
104+
$state = $view->getState();
105+
106+
$pendingCount = count($changelog->getList($state->getVersionId(), $currentVersionId));
107+
108+
$pendingString = "<error>$pendingCount</error>";
109+
if ($pendingCount <= 0) {
110+
$pendingString = "<info>$pendingCount</info>";
111+
}
112+
113+
return $pendingString;
49114
}
50115
}

app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerStatusCommandTest.php

Lines changed: 159 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
use Magento\Framework\Indexer\StateInterface;
99
use Magento\Indexer\Console\Command\IndexerStatusCommand;
1010
use Symfony\Component\Console\Tester\CommandTester;
11+
use Symfony\Component\Console\Helper\HelperSet;
12+
use Symfony\Component\Console\Helper\TableHelper;
1113

1214
class IndexerStatusCommandTest extends AbstractIndexerCommandCommonSetup
1315
{
@@ -18,35 +20,134 @@ class IndexerStatusCommandTest extends AbstractIndexerCommandCommonSetup
1820
*/
1921
private $command;
2022

23+
/**
24+
* @param \PHPUnit_Framework_MockObject_MockObject $indexerMock
25+
* @param array $data
26+
* @return mixed
27+
*/
28+
private function attachViewToIndexerMock($indexerMock, array $data)
29+
{
30+
/** @var \Magento\Framework\Mview\View\Changelog|\PHPUnit_Framework_MockObject_MockObject $changelog */
31+
$changelog = $this->getMockBuilder(\Magento\Framework\Mview\View\Changelog::class)
32+
->disableOriginalConstructor()
33+
->getMock();
34+
35+
$changelog->expects($this->any())
36+
->method('getList')
37+
->willReturn(range(0, $data['view']['changelog']['list_size']-1));
38+
39+
/** @var \Magento\Indexer\Model\Mview\View\State|\PHPUnit_Framework_MockObject_MockObject $stateMock */
40+
$stateMock = $this->getMockBuilder(\Magento\Indexer\Model\Mview\View\State::class)
41+
->disableOriginalConstructor()
42+
->setMethods(null)
43+
->getMock();
44+
45+
$stateMock->addData($data['view']['state']);
46+
47+
/** @var \Magento\Framework\Mview\View|\PHPUnit_Framework_MockObject_MockObject $viewMock */
48+
$viewMock = $this->getMockBuilder(\Magento\Framework\Mview\View::class)
49+
->disableOriginalConstructor()
50+
->setMethods(['getChangelog', 'getState'])
51+
->getMock();
52+
53+
$viewMock->expects($this->any())
54+
->method('getState')
55+
->willReturn($stateMock);
56+
$viewMock->expects($this->any())
57+
->method('getChangelog')
58+
->willReturn($changelog);
59+
60+
$indexerMock->method('getView')
61+
->willReturn($viewMock);
62+
63+
return $indexerMock;
64+
}
65+
2166
/**
2267
* @param array $indexers
23-
* @param array $statuses
68+
*
2469
* @dataProvider executeAllDataProvider
2570
*/
26-
public function testExecuteAll(array $indexers, array $statuses)
71+
public function testExecuteAll(array $indexers)
2772
{
2873
$this->configureAdminArea();
2974
$indexerMocks = [];
3075
foreach ($indexers as $indexerData) {
3176
$indexerMock = $this->getIndexerMock(
32-
['getStatus'],
77+
['getStatus', 'isScheduled', 'getState', 'getView'],
3378
$indexerData
3479
);
80+
3581
$indexerMock->method('getStatus')
36-
->willReturn($statuses[$indexerData['indexer_id']]);
82+
->willReturn($indexerData['status']);
83+
$indexerMock->method('isScheduled')
84+
->willReturn($indexerData['is_scheduled']);
85+
86+
if ($indexerData['is_scheduled']) {
87+
$this->attachViewToIndexerMock($indexerMock, $indexerData);
88+
}
89+
3790
$indexerMocks[] = $indexerMock;
3891
}
92+
3993
$this->initIndexerCollectionByItems($indexerMocks);
4094
$this->command = new IndexerStatusCommand($this->objectManagerFactory);
95+
96+
$objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
97+
98+
$this->command->setHelperSet(
99+
$objectManager->getObject(
100+
HelperSet::class,
101+
['helpers' => [$objectManager->getObject(TableHelper::class)]]
102+
)
103+
);
104+
41105
$commandTester = new CommandTester($this->command);
42106
$commandTester->execute([]);
43-
$actualValue = $commandTester->getDisplay();
44-
$expectedValue = sprintf('%-50s ', 'Title_indexerOne' . ':') . 'Ready' . PHP_EOL
45-
. sprintf('%-50s ', 'Title_indexerTwo' . ':') . 'Reindex required' . PHP_EOL
46-
. sprintf('%-50s ', 'Title_indexerThree' . ':') . 'Processing' . PHP_EOL
47-
. sprintf('%-50s ', 'Title_indexerFour' . ':') . 'unknown' . PHP_EOL;
48107

49-
$this->assertStringStartsWith($expectedValue, $actualValue);
108+
$linesOutput = array_filter(explode(PHP_EOL, $commandTester->getDisplay()));
109+
110+
$spacer = '+----------------+------------------+-----------+-------------------------+---------------------+';
111+
112+
$this->assertCount(8, $linesOutput, 'There should be 8 lines output. 3 Spacers, 1 header, 4 content.');
113+
$this->assertEquals($linesOutput[0], $spacer, "Lines 0, 2, 7 should be spacer lines");
114+
$this->assertEquals($linesOutput[2], $spacer, "Lines 0, 2, 7 should be spacer lines");
115+
$this->assertEquals($linesOutput[7], $spacer, "Lines 0, 2, 7 should be spacer lines");
116+
117+
$headerValues = array_values(array_filter(explode('|', $linesOutput[1])));
118+
$this->assertEquals('Title', trim($headerValues[0]));
119+
$this->assertEquals('Status', trim($headerValues[1]));
120+
$this->assertEquals('Update On', trim($headerValues[2]));
121+
$this->assertEquals('Schedule Status', trim($headerValues[3]));
122+
$this->assertEquals('Schedule Updated', trim($headerValues[4]));
123+
124+
$indexer1 = array_values(array_filter(explode('|', $linesOutput[3])));
125+
$this->assertEquals('Title_indexer1', trim($indexer1[0]));
126+
$this->assertEquals('Ready', trim($indexer1[1]));
127+
$this->assertEquals('Schedule', trim($indexer1[2]));
128+
$this->assertEquals('idle (10 in backlog)', trim($indexer1[3]));
129+
$this->assertEquals('2017-01-01 11:11:11', trim($indexer1[4]));
130+
131+
$indexer2 = array_values(array_filter(explode('|', $linesOutput[4])));
132+
$this->assertEquals('Title_indexer2', trim($indexer2[0]));
133+
$this->assertEquals('Reindex required', trim($indexer2[1]));
134+
$this->assertEquals('Save', trim($indexer2[2]));
135+
$this->assertEquals('', trim($indexer2[3]));
136+
$this->assertEquals('', trim($indexer2[4]));
137+
138+
$indexer3 = array_values(array_filter(explode('|', $linesOutput[5])));
139+
$this->assertEquals('Title_indexer3', trim($indexer3[0]));
140+
$this->assertEquals('Processing', trim($indexer3[1]));
141+
$this->assertEquals('Schedule', trim($indexer3[2]));
142+
$this->assertEquals('idle (100 in backlog)', trim($indexer3[3]));
143+
$this->assertEquals('2017-01-01 11:11:11', trim($indexer3[4]));
144+
145+
$indexer4 = array_values(array_filter(explode('|', $linesOutput[6])));
146+
$this->assertEquals('Title_indexer4', trim($indexer4[0]));
147+
$this->assertEquals('unknown', trim($indexer4[1]));
148+
$this->assertEquals('Schedule', trim($indexer4[2]));
149+
$this->assertEquals('running (20 in backlog)', trim($indexer4[3]));
150+
$this->assertEquals('2017-01-01 11:11:11', trim($indexer4[4]));
50151
}
51152

52153
/**
@@ -59,27 +160,65 @@ public function executeAllDataProvider()
59160
'indexers' => [
60161
'indexer_1' => [
61162
'indexer_id' => 'indexer_1',
62-
'title' => 'Title_indexerOne'
163+
'title' => 'Title_indexer1',
164+
'status' => StateInterface::STATUS_VALID,
165+
'is_scheduled' => true,
166+
'view' => [
167+
'state' => [
168+
'status' => 'idle',
169+
'updated' => '2017-01-01 11:11:11',
170+
],
171+
'changelog' => [
172+
'list_size' => 10
173+
]
174+
]
63175
],
64176
'indexer_2' => [
65177
'indexer_id' => 'indexer_2',
66-
'title' => 'Title_indexerTwo'
178+
'title' => 'Title_indexer2',
179+
'status' => StateInterface::STATUS_INVALID,
180+
'is_scheduled' => false,
181+
'view' => [
182+
'state' => [
183+
'status' => 'idle',
184+
'updated' => '2017-01-01 11:11:11',
185+
],
186+
'changelog' => [
187+
'list_size' => 99999999
188+
]
189+
]
67190
],
68191
'indexer_3' => [
69192
'indexer_id' => 'indexer_3',
70-
'title' => 'Title_indexerThree'
193+
'title' => 'Title_indexer3',
194+
'status' => StateInterface::STATUS_WORKING,
195+
'is_scheduled' => true,
196+
'view' => [
197+
'state' => [
198+
'status' => 'idle',
199+
'updated' => '2017-01-01 11:11:11',
200+
],
201+
'changelog' => [
202+
'list_size' => 100
203+
]
204+
]
71205
],
72206
'indexer_4' => [
73207
'indexer_id' => 'indexer_4',
74-
'title' => 'Title_indexerFour'
208+
'title' => 'Title_indexer4',
209+
'status' => null,
210+
'is_scheduled' => true,
211+
'view' => [
212+
'state' => [
213+
'status' => 'running',
214+
'updated' => '2017-01-01 11:11:11',
215+
],
216+
'changelog' => [
217+
'list_size' => 20
218+
]
219+
]
75220
],
76221
],
77-
'Statuses' => [
78-
'indexer_1' => StateInterface::STATUS_VALID,
79-
'indexer_2' => StateInterface::STATUS_INVALID,
80-
'indexer_3' => StateInterface::STATUS_WORKING,
81-
'indexer_4' => null,
82-
]
83222
],
84223
];
85224
}

0 commit comments

Comments
 (0)