Skip to content

Commit 10b62a8

Browse files
authored
Merge pull request #3629 from rbayet/feature-3600-indices-grid-remove-all-ghost-indices-button-reworked
[Indices] Feature #3624, add a cli command to remove all ghost indices
2 parents df2114b + 475939d commit 10b62a8

File tree

4 files changed

+213
-48
lines changed

4 files changed

+213
-48
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
/**
3+
* DISCLAIMER
4+
*
5+
* Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer versions in the future.
6+
*
7+
* @category Smile
8+
* @package Smile\ElasticsuiteIndices
9+
* @author Vadym Honcharuk <[email protected]>
10+
* @copyright 2025 Smile
11+
* @license Open Software License ("OSL") v. 3.0
12+
*/
13+
14+
namespace Smile\ElasticsuiteIndices\Console\Command;
15+
16+
use Exception;
17+
use Magento\Framework\Console\Cli;
18+
use Smile\ElasticsuiteIndices\Model\GhostIndexPurger;
19+
use Symfony\Component\Console\Command\Command;
20+
use Symfony\Component\Console\Input\InputInterface;
21+
use Symfony\Component\Console\Output\OutputInterface;
22+
23+
/**
24+
* CLI command to purge ghost indices.
25+
*
26+
* This command uses the GhostIndexPurger service to remove all indices detected as "ghost".
27+
* It is intended for use when the number of ghost indices is large, which could cause timeouts in the Admin UI.
28+
*
29+
* @category Smile
30+
* @package Smile\ElasticsuiteIndices
31+
* @author Vadym Honcharuk <[email protected]>
32+
*/
33+
class PurgeGhostIndices extends Command
34+
{
35+
/**
36+
* @var GhostIndexPurger
37+
*/
38+
private GhostIndexPurger $ghostIndexPurger;
39+
40+
/**
41+
* Constructor.
42+
*
43+
* @param GhostIndexPurger $ghostIndexPurger Ghost index purging service.
44+
*/
45+
public function __construct(GhostIndexPurger $ghostIndexPurger)
46+
{
47+
parent::__construct();
48+
$this->ghostIndexPurger = $ghostIndexPurger;
49+
}
50+
51+
/**
52+
* {@inheritdoc}
53+
*/
54+
protected function configure()
55+
{
56+
$this->setName('elasticsuite:indices:purgeghosts');
57+
$this->setDescription('Purge all ghost indices.');
58+
}
59+
60+
/**
61+
* {@inheritdoc}
62+
* @throws Exception
63+
*/
64+
protected function execute(InputInterface $input, OutputInterface $output): int
65+
{
66+
try {
67+
$count = $this->ghostIndexPurger->purge();
68+
$output->writeln(sprintf('<info>%s ghost indices were deleted.</info>', $count));
69+
} catch (Exception $e) {
70+
$output->writeln('<error>An error occurred while purging ghost indices.</error>');
71+
72+
return Cli::RETURN_FAILURE;
73+
}
74+
75+
return Cli::RETURN_SUCCESS;
76+
}
77+
}

src/module-elasticsuite-indices/Controller/Adminhtml/Index/RemoveGhostIndices.php

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@
1515

1616
use Exception;
1717
use Magento\Backend\App\Action\Context;
18-
use Smile\ElasticsuiteIndices\Block\Widget\Grid\Column\Renderer\IndexStatus;
1918
use Smile\ElasticsuiteIndices\Controller\Adminhtml\AbstractAction;
20-
use Smile\ElasticsuiteIndices\Model\IndexStatsProvider;
21-
use Smile\ElasticsuiteIndices\Model\IndexStatusProvider;
19+
use Smile\ElasticsuiteIndices\Model\GhostIndexPurger;
2220

2321
/**
24-
* Controller for removing all ghost indices.
22+
* Controller for removing ghost indices.
2523
*
2624
* @category Smile
2725
* @package Smile\ElasticsuiteIndices
@@ -35,35 +33,28 @@ class RemoveGhostIndices extends AbstractAction
3533
public const ADMIN_RESOURCE = 'Smile_ElasticsuiteIndices::remove';
3634

3735
/**
38-
* @var IndexStatsProvider
36+
* @var GhostIndexPurger
3937
*/
40-
private IndexStatsProvider $indexStatsProvider;
41-
42-
/**
43-
* @var IndexStatusProvider
44-
*/
45-
private IndexStatusProvider $indexStatusProvider;
38+
private GhostIndexPurger $ghostIndexPurger;
4639

4740
/**
4841
* Constructor.
4942
*
50-
* @param Context $context The current context.
51-
* @param IndexStatsProvider $indexStatsProvider Index stats provider.
52-
* @param IndexStatusProvider $indexStatusProvider Index status provider.
43+
* @param Context $context The current context.
44+
* @param GhostIndexPurger $ghostIndexPurger Ghost index purging service.
5345
*/
5446
public function __construct(
5547
Context $context,
56-
IndexStatsProvider $indexStatsProvider,
57-
IndexStatusProvider $indexStatusProvider
48+
GhostIndexPurger $ghostIndexPurger
5849
) {
5950
parent::__construct($context);
60-
$this->indexStatsProvider = $indexStatsProvider;
61-
$this->indexStatusProvider = $indexStatusProvider;
51+
$this->ghostIndexPurger = $ghostIndexPurger;
6252
}
6353

6454
/**
6555
* {@inheritdoc}
6656
* @SuppressWarnings(PHPMD.ElseExpression)
57+
* @throws Exception
6758
*/
6859
public function execute()
6960
{
@@ -73,41 +64,14 @@ public function execute()
7364
return $this->_redirect($this->_redirect->getRefererUrl());
7465
}
7566

76-
$deleted = [];
77-
78-
$indices = $this->indexStatsProvider->getElasticSuiteIndices();
79-
80-
foreach ($indices as $indexName => $alias) {
81-
if ($this->indexCanBeRemoved($indexName, $alias)) {
82-
try {
83-
$this->indexStatsProvider->deleteIndex($indexName);
84-
$deleted[] = $indexName;
85-
} catch (Exception $e) {
86-
// Optional: Log the exception if needed.
87-
}
88-
}
89-
}
67+
$deletedCount = $this->ghostIndexPurger->purge();
9068

91-
if (!empty($deleted)) {
92-
$count = count($deleted);
93-
$this->messageManager->addSuccessMessage(__('%1 ghost indices were deleted.', $count));
69+
if ($deletedCount > 0) {
70+
$this->messageManager->addSuccessMessage(__('%1 ghost indices were deleted.', $deletedCount));
9471
} else {
9572
$this->messageManager->addNoticeMessage(__('No ghost indices were deleted.'));
9673
}
9774

9875
return $this->_redirect($this->_redirect->getRefererUrl());
9976
}
100-
101-
/**
102-
* Determines if the index can be safely removed (is ghost).
103-
*
104-
* @param string $indexName Index name.
105-
* @param string|null $alias Index alias.
106-
* @return bool
107-
*/
108-
private function indexCanBeRemoved(string $indexName, ?string $alias): bool
109-
{
110-
return $this->_isAllowed()
111-
&& $this->indexStatusProvider->getIndexStatus($indexName, $alias) === IndexStatus::GHOST_STATUS;
112-
}
11377
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
/**
3+
* DISCLAIMER
4+
*
5+
* Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer versions in the future.
6+
*
7+
* @category Smile
8+
* @package Smile\ElasticsuiteIndices
9+
* @author Vadym Honcharuk <[email protected]>
10+
* @copyright 2025 Smile
11+
* @license Open Software License ("OSL") v. 3.0
12+
*/
13+
14+
namespace Smile\ElasticsuiteIndices\Model;
15+
16+
use Exception;
17+
use Smile\ElasticsuiteIndices\Block\Widget\Grid\Column\Renderer\IndexStatus;
18+
19+
/**
20+
* Service class responsible for purging ghost indices.
21+
*
22+
* @category Smile
23+
* @package Smile\ElasticsuiteIndices
24+
* @author Vadym Honcharuk <[email protected]>
25+
*/
26+
class GhostIndexPurger
27+
{
28+
/**
29+
* @var IndexStatsProvider
30+
*/
31+
private IndexStatsProvider $indexStatsProvider;
32+
33+
/**
34+
* @var IndexStatusProvider
35+
*/
36+
private IndexStatusProvider $indexStatusProvider;
37+
38+
/**
39+
* Constructor.
40+
*
41+
* @param IndexStatsProvider $indexStatsProvider Index stats provider.
42+
* @param IndexStatusProvider $indexStatusProvider Index status provider.
43+
*/
44+
public function __construct(
45+
IndexStatsProvider $indexStatsProvider,
46+
IndexStatusProvider $indexStatusProvider
47+
) {
48+
$this->indexStatsProvider = $indexStatsProvider;
49+
$this->indexStatusProvider = $indexStatusProvider;
50+
}
51+
52+
/**
53+
* Purge all ghost indices.
54+
*
55+
* Iterates through all known ElasticSuite indices and deletes those determined
56+
* to be in "ghost" status (i.e., no longer attached to any alias and considered safe to delete).
57+
*
58+
* @return int
59+
* @throws Exception
60+
*/
61+
public function purge(): int
62+
{
63+
$deleted = [];
64+
65+
$indices = $this->indexStatsProvider->getElasticSuiteIndices();
66+
67+
foreach ($indices as $indexName => $alias) {
68+
if ($this->indexCanBeRemoved($indexName, $alias)) {
69+
try {
70+
$this->indexStatsProvider->deleteIndex($indexName);
71+
$deleted[] = $indexName;
72+
} catch (Exception $e) {
73+
// Optional: Log the exception if needed.
74+
}
75+
}
76+
}
77+
78+
return count($deleted);
79+
}
80+
81+
/**
82+
* Determines if the index can be safely removed (is ghost).
83+
*
84+
* @param string $indexName Index name.
85+
* @param string|null $alias Index alias.
86+
*
87+
* @return bool
88+
*/
89+
private function indexCanBeRemoved(string $indexName, ?string $alias): bool
90+
{
91+
return $this->indexStatusProvider->getIndexStatus($indexName, $alias) === IndexStatus::GHOST_STATUS;
92+
}
93+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Smile_ElasticsuiteIndices dependency injection configuration.
5+
*
6+
* DISCLAIMER
7+
*
8+
* Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer versions in the future.
9+
*
10+
* @category Smile
11+
* @package Smile\ElasticsuiteIndices
12+
* @author Vadym Honcharuk <[email protected]>
13+
* @copyright 2025 Smile
14+
* @license Open Software License ("OSL") v. 3.0
15+
*/
16+
-->
17+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
18+
<type name="Magento\Framework\Console\CommandList">
19+
<arguments>
20+
<argument name="commands" xsi:type="array">
21+
<item name="elasticsuiteIndicesPurgeGhostIndices" xsi:type="object">Smile\ElasticsuiteIndices\Console\Command\PurgeGhostIndices</item>
22+
</argument>
23+
</arguments>
24+
</type>
25+
26+
<type name="Smile\ElasticsuiteIndices\Console\Command\PurgeGhostIndices">
27+
<arguments>
28+
<argument name="ghostIndexPurger" xsi:type="object">Smile\ElasticsuiteIndices\Model\GhostIndexPurger\Proxy</argument>
29+
</arguments>
30+
</type>
31+
</config>

0 commit comments

Comments
 (0)