Skip to content

"Clear" and "Swap" commands #51

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions main/src/Console/Command/ClearCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace IntegerNet\Solr\Console\Command;

use IntegerNet\Solr\Indexer\Slice;
use IntegerNet\Solr\Model\Indexer;
use Magento\Framework\App;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
* solr:clear command
*/
class ClearCommand extends Command
{
const INPUT_STORES = 'stores';
const INPUT_USESWAPCORE = 'useswapcore';
/**
* @var Indexer\Console
*/
private $indexer;
/**
* @var App\State
*/
private $appState;

public function __construct(Indexer\Console $indexer, App\State $appState, $name = null)
{
parent::__construct($name);
$this->indexer = $indexer;
$this->appState = $appState;
}

protected function configure()
{
$options = [
new InputOption(
self::INPUT_STORES,
null,
InputOption::VALUE_OPTIONAL,
'Clear solr product index for given stores (can be store id, store code, comma seperated. Or "all".) '
. 'If not set, clear all stores.'
),
new InputOption(
self::INPUT_USESWAPCORE,
null,
InputOption::VALUE_NONE,
'Use swap core for clearing instead of live solr core (only if configured correctly).'
),
];
$this->setName('solr:clear');
$this->setHelp('Clear Solr index for given stores (see "stores" param).');
$this->setDescription('Clear Solr index');
$this->setDefinition($options);
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$styledOutput = new StyledOutput(
$output,
class_exists(SymfonyStyle::class) ? new SymfonyStyle($input, $output) : null
);
$startTime = microtime(true);
$this->appState->setAreaCode(App\Area::AREA_GLOBAL);
if (!$input->getOption(self::INPUT_STORES) || $input->getOption(self::INPUT_STORES) === 'all') {
$stores = null;
$styledOutput->title('Clearing full Solr product index...');
} else {
$stores = \explode(',', $input->getOption(self::INPUT_STORES));
$styledOutput->title('Clearing Solr product index for stores ' . \implode(', ', $stores) . '...');
}
try {
$this->indexer->addProgressHandler(
new ProgressInConsole($output)
);
if ($input->getOption(self::INPUT_USESWAPCORE)) {
$this->indexer->clearStoresOnSwappedCore($stores);
} else {
$this->indexer->clearStores($stores);
}
$totalTime = number_format(microtime(true) - $startTime, 2);
$styledOutput->success("Clearing finished in $totalTime seconds.");
} catch (\Exception $e) {
$styledOutput->error($e->getMessage());
}
}
}
19 changes: 11 additions & 8 deletions main/src/Console/Command/ReindexCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
*/
class ReindexCommand extends Command
{
const INPUT_STORES = 'stores';
const INPUT_STORES = 'stores';
const INPUT_EMPTYINDEX = 'emptyindex';
const INPUT_NOEMPTYINDEX = 'noemptyindex';
const INPUT_PROGRESS = 'progress';
/**
* @var Indexer\Console
*/
Expand All @@ -38,26 +41,26 @@ protected function configure()
{
$options = [
new InputOption(
'stores',
self::INPUT_STORES,
null,
InputOption::VALUE_OPTIONAL,
'Reindex given stores (can be store id, store code, comma seperated. Or "all".) '
. 'If not set, reindex all stores.'
),
new InputOption(
'emptyindex',
self::INPUT_EMPTYINDEX,
null,
InputOption::VALUE_NONE,
'Force emptying the solr index for the given store(s). If not set, configured value is used.'
),
new InputOption(
'noemptyindex',
self::INPUT_NOEMPTYINDEX,
null,
InputOption::VALUE_NONE,
'Force not emptying the solr index for the given store(s). If not set, configured value is used.'
),
new InputOption(
'progress',
self::INPUT_PROGRESS,
null,
InputOption::VALUE_NONE,
'Show progress bar.'
Expand Down Expand Up @@ -88,13 +91,13 @@ class_exists(SymfonyStyle::class) ? new SymfonyStyle($input, $output) : null
$this->indexer->addProgressHandler(
new ProgressInConsole(
$output,
$input->getOption('progress') ? ProgressInConsole::USE_PROGRESS_BAR : false
$input->getOption(self::INPUT_PROGRESS) ? ProgressInConsole::USE_PROGRESS_BAR : false
)
);
if ($input->getOption('emptyindex')) {
if ($input->getOption(self::INPUT_EMPTYINDEX)) {
$styledOutput->note('Forcing empty index.');
$this->indexer->executeStoresForceEmpty($stores);
} elseif ($input->getOption('noemptyindex')) {
} elseif ($input->getOption(self::INPUT_NOEMPTYINDEX)) {
$styledOutput->note('Forcing non-empty index.');
$this->indexer->executeStoresForceNotEmpty($stores);
} else {
Expand Down
31 changes: 20 additions & 11 deletions main/src/Console/Command/ReindexSliceCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
*/
class ReindexSliceCommand extends Command
{
const INPUT_STORES = 'stores';
const INPUT_STORES = 'stores';
const INPUT_SLICE = 'slice';
const INPUT_USESWAPCORE = 'useswapcore';
const INPUT_PROGRESS = 'progress';
/**
* @var Indexer\Console
*/
Expand All @@ -38,33 +41,36 @@ protected function configure()
{
$options = [
new InputOption(
'stores',
self::INPUT_STORES,
null,
InputOption::VALUE_OPTIONAL,
'Reindex given stores (can be store id, store code, comma seperated. Or "all".) '
. 'If not set, reindex all stores.'
),
new InputOption(
'slice',
self::INPUT_SLICE,
null,
InputOption::VALUE_REQUIRED,
'<number>/<total_number>, i.e. "1/5" or "2/5". '
),
new InputOption(
'useswapcore',
self::INPUT_USESWAPCORE,
null,
InputOption::VALUE_NONE,
'Use swap core for indexing instead of live solr core (only if configured correctly).'
),
new InputOption(
'progress',
self::INPUT_PROGRESS,
null,
InputOption::VALUE_NONE,
'Show progress bar.'
)
];
$this->setName('solr:reindex:slice');
$this->setHelp('Partially reindex Solr for given stores (see "stores" param). Can be used for letting indexing run in parallel.');
$this->setHelp(
'Partially reindex Solr for given stores (see "stores" param). '
. 'Can be used for letting indexing run in parallel.'
);
$this->setDescription('Partially reindex Solr');
$this->setDefinition($options);
}
Expand All @@ -88,17 +94,20 @@ class_exists(SymfonyStyle::class) ? new SymfonyStyle($input, $output) : null
$this->indexer->addProgressHandler(
new ProgressInConsole(
$output,
$input->getOption('progress') ? ProgressInConsole::USE_PROGRESS_BAR : false
$input->getOption(self::INPUT_PROGRESS) ? ProgressInConsole::USE_PROGRESS_BAR : false
)
);
$styledOutput->note('Processing slice ' . $input->getOption('slice') . '...');
if ($input->getOption('useswapcore')) {
$styledOutput->note('Processing slice ' . $input->getOption(self::INPUT_SLICE) . '...');
if ($input->getOption(self::INPUT_USESWAPCORE)) {
$this->indexer->executeStoresSliceOnSwappedCore(
Slice::fromExpression($input->getOption('slice')),
Slice::fromExpression($input->getOption(self::INPUT_SLICE)),
$stores
);
} else {
$this->indexer->executeStoresSlice(Slice::fromExpression($input->getOption('slice')), $stores);
$this->indexer->executeStoresSlice(
Slice::fromExpression($input->getOption(self::INPUT_SLICE)),
$stores
);
}
$totalTime = number_format(microtime(true) - $startTime, 2);
$styledOutput->success("Reindex finished in $totalTime seconds.");
Expand Down
84 changes: 84 additions & 0 deletions main/src/Console/Command/SwapCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

namespace IntegerNet\Solr\Console\Command;

use IntegerNet\Solr\Indexer\Slice;
use IntegerNet\Solr\Model\Indexer;
use Magento\Framework\App;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
* solr:swap command
*/
class SwapCommand extends Command
{
const INPUT_STORES = 'stores';

/**
* @var Indexer\Console
*/
private $indexer;
/**
* @var App\State
*/
private $appState;

public function __construct(Indexer\Console $indexer, App\State $appState, $name = null)
{
parent::__construct($name);
$this->indexer = $indexer;
$this->appState = $appState;
}

protected function configure()
{
$options = [
new InputOption(
self::INPUT_STORES,
null,
InputOption::VALUE_OPTIONAL,
'Swap cores for given stores (can be store id, store code, comma seperated. Or "all".) '
. 'If not set, swap cores for all stores.'
),
];
$this->setName('solr:swap');
$this->setHelp(
'Swap cores. This is useful if using slices (see solr:reindex:slice) '
. 'after indexing with the "--use_swap_core" param; it\'s not needed otherwise.'
);
$this->setDescription('Swap cores');
$this->setDefinition($options);
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$styledOutput = new StyledOutput(
$output,
class_exists(SymfonyStyle::class) ? new SymfonyStyle($input, $output) : null
);
$startTime = microtime(true);
$this->appState->setAreaCode(App\Area::AREA_GLOBAL);
if (!$input->getOption(self::INPUT_STORES) || $input->getOption(self::INPUT_STORES) === 'all') {
$stores = null;
$styledOutput->title('Swap all cores...');
} else {
$stores = \explode(',', $input->getOption(self::INPUT_STORES));
$styledOutput->title('Swap cores for stores ' . \implode(', ', $stores) . '...');
}
try {
$this->indexer->addProgressHandler(
new ProgressInConsole($output)
);
$this->indexer->swapCores($stores);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you call $this->indexer->checkSwapCoresConfiguration($stores) before? If you don't have the configuration right, it could severely mess up the index (i.e. two stores sharing a core, but only one of the stores is being swapped).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done it in Console:swapCores() now, which is called here

$totalTime = number_format(microtime(true) - $startTime, 2);
$styledOutput->success("Core swap finished in $totalTime seconds.");
} catch (\Exception $e) {
$styledOutput->error($e->getMessage());
}
}
}
34 changes: 31 additions & 3 deletions main/src/Model/Indexer/Console.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use IntegerNet\Solr\Indexer\ProductIndexer;
use IntegerNet\Solr\Indexer\Progress\ProgressHandler;
use IntegerNet\Solr\Indexer\Slice;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\StoreManagerInterface;

class Console
Expand Down Expand Up @@ -64,15 +65,42 @@ public function executeStoresSliceOnSwappedCore($slice, $storeIds)

public function clearStores(array $storeIds = null)
{
//TODO fetch all store ids if NULL
if (empty($storeIds)) {
throw new \BadMethodCallException("Command for 'clear all stores' not implemented yet");
$storeIds = array_map(
function (StoreInterface $store) {
return $store->getId();
},
$this->storeManager->getStores()
);
}
foreach ($this->getStoreIds($storeIds) as $storeId) {
$this->solrIndexer->clearIndex($storeId);
}
}

public function clearStoresOnSwappedCore(array $storeIds = null)
{
if (empty($storeIds)) {
$storeIds = array_map(
function (StoreInterface $store) {
return $store->getId();
},
$this->storeManager->getStores()
);
}
$this->solrIndexer->activateSwapCore();
foreach ($this->getStoreIds($storeIds) as $storeId) {
$this->solrIndexer->clearIndex($storeId);
}
$this->solrIndexer->deactivateSwapCore();
}

public function swapCores(array $storeIds = null)
{
$this->solrIndexer->checkSwapCoresConfiguration($storeIds);
$this->solrIndexer->swapCores($storeIds);
}

public function addProgressHandler(ProgressHandler $handler)
{
$this->solrIndexer->addProgressHandler($handler);
Expand Down Expand Up @@ -122,7 +150,7 @@ function ($storeId) use ($storesByCode) {
if (isset($storesByCode[$storeId])) {
return $storesByCode[$storeId]->getId();
}
throw new \InvalidArgumentException("'$storeId' is neither a numric ID nor an existing store code");
throw new \InvalidArgumentException("'$storeId' is neither a numeric ID nor an existing store code");
},
$storeIds
);
Expand Down
Loading