2011-04-12 04:27:47 +02:00
< ? php
2013-03-27 18:44:06 +01:00
namespace FOS\ElasticaBundle\Command ;
2011-04-12 04:27:47 +02:00
2011-06-21 19:23:25 +02:00
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand ;
2013-10-08 12:00:04 +02:00
use Symfony\Component\Console\Helper\DialogHelper ;
2011-04-12 04:27:47 +02:00
use Symfony\Component\Console\Input\InputOption ;
use Symfony\Component\Console\Input\InputInterface ;
use Symfony\Component\Console\Output\OutputInterface ;
2013-03-27 19:58:34 +01:00
use FOS\ElasticaBundle\IndexManager ;
use FOS\ElasticaBundle\Provider\ProviderRegistry ;
use FOS\ElasticaBundle\Resetter ;
use FOS\ElasticaBundle\Provider\ProviderInterface ;
2015-01-07 18:42:15 +01:00
use Symfony\Component\Console\Helper\ProgressBar ;
2011-04-12 04:27:47 +02:00
/**
* Populate the search index
*/
2011-06-21 19:23:25 +02:00
class PopulateCommand extends ContainerAwareCommand
2011-04-12 04:27:47 +02:00
{
/**
2013-03-02 12:23:44 +01:00
* @ var IndexManager
2012-03-12 17:02:25 +01:00
*/
private $indexManager ;
/**
2013-03-02 12:23:44 +01:00
* @ var ProviderRegistry
2012-03-12 17:02:25 +01:00
*/
private $providerRegistry ;
/**
2013-03-02 12:23:44 +01:00
* @ var Resetter
2012-03-12 17:02:25 +01:00
*/
private $resetter ;
/**
* @ see Symfony\Component\Console\Command\Command :: configure ()
2011-04-12 04:27:47 +02:00
*/
protected function configure ()
{
$this
2013-03-27 18:44:06 +01:00
-> setName ( 'fos:elastica:populate' )
2012-03-12 17:02:25 +01:00
-> addOption ( 'index' , null , InputOption :: VALUE_OPTIONAL , 'The index to repopulate' )
-> addOption ( 'type' , null , InputOption :: VALUE_OPTIONAL , 'The type to repopulate' )
2013-02-22 20:03:40 +01:00
-> addOption ( 'no-reset' , null , InputOption :: VALUE_NONE , 'Do not reset index before populating' )
2013-10-08 12:00:04 +02:00
-> addOption ( 'offset' , null , InputOption :: VALUE_REQUIRED , 'Start indexing at offset' , 0 )
-> addOption ( 'sleep' , null , InputOption :: VALUE_REQUIRED , 'Sleep time between persisting iterations (microseconds)' , 0 )
-> addOption ( 'batch-size' , null , InputOption :: VALUE_REQUIRED , 'Index packet size (overrides provider config option)' )
2014-02-19 11:01:54 +01:00
-> addOption ( 'ignore-errors' , null , InputOption :: VALUE_NONE , 'Do not stop on errors' )
2012-03-12 17:02:25 +01:00
-> setDescription ( 'Populates search indexes from providers' )
;
}
/**
* @ see Symfony\Component\Console\Command\Command :: initialize ()
*/
protected function initialize ( InputInterface $input , OutputInterface $output )
{
2013-03-27 18:44:06 +01:00
$this -> indexManager = $this -> getContainer () -> get ( 'fos_elastica.index_manager' );
$this -> providerRegistry = $this -> getContainer () -> get ( 'fos_elastica.provider_registry' );
$this -> resetter = $this -> getContainer () -> get ( 'fos_elastica.resetter' );
2011-04-12 04:27:47 +02:00
}
/**
2012-03-12 17:02:25 +01:00
* @ see Symfony\Component\Console\Command\Command :: execute ()
2011-04-12 04:27:47 +02:00
*/
protected function execute ( InputInterface $input , OutputInterface $output )
{
2013-10-08 12:00:04 +02:00
$index = $input -> getOption ( 'index' );
$type = $input -> getOption ( 'type' );
2014-02-20 22:58:43 +01:00
$reset = ! $input -> getOption ( 'no-reset' );
2013-10-08 12:00:04 +02:00
$options = $input -> getOptions ();
2014-02-19 11:01:54 +01:00
$options [ 'ignore-errors' ] = $input -> hasOption ( 'ignore-errors' );
2014-01-24 14:20:10 +01:00
if ( $input -> isInteractive () && $reset && $input -> getOption ( 'offset' )) {
2013-10-08 12:00:04 +02:00
/** @var DialogHelper $dialog */
$dialog = $this -> getHelperSet () -> get ( 'dialog' );
if ( ! $dialog -> askConfirmation ( $output , '<question>You chose to reset the index and start indexing with an offset. Do you really want to do that?</question>' , true )) {
return ;
}
}
2012-03-12 17:02:25 +01:00
if ( null === $index && null !== $type ) {
throw new \InvalidArgumentException ( 'Cannot specify type option without an index.' );
}
if ( null !== $index ) {
if ( null !== $type ) {
2013-10-08 12:00:04 +02:00
$this -> populateIndexType ( $output , $index , $type , $reset , $options );
2012-03-12 17:02:25 +01:00
} else {
2013-10-08 12:00:04 +02:00
$this -> populateIndex ( $output , $index , $reset , $options );
2012-03-12 17:02:25 +01:00
}
} else {
$indexes = array_keys ( $this -> indexManager -> getAllIndexes ());
foreach ( $indexes as $index ) {
2013-10-08 12:00:04 +02:00
$this -> populateIndex ( $output , $index , $reset , $options );
2012-03-12 17:02:25 +01:00
}
}
}
2015-01-22 01:18:51 +01:00
/**
* @ param ProviderInterface $provider
* @ param OutputInterface $output
* @ param string $input
* @ param string $type
* @ param array $options
*/
private function doPopulateType ( ProviderInterface $provider , OutputInterface $output , $input , $type , $options )
{
$loggerClosure = $this -> getLoggerClosure ( $output , $input , $type );
$provider -> populate ( $loggerClosure , $options );
}
/**
* Builds a loggerClosure to be called from inside the Provider to update the command
* line .
*
* @ param OutputInterface $output
* @ param string $index
* @ param string $type
* @ return callable
*/
private function getLoggerClosure ( OutputInterface $output , $index , $type )
{
if ( ! class_exists ( 'Symfony\Component\Console\Helper\ProgressBar' )) {
$lastStep = null ;
$current = 0 ;
return function ( $increment , $totalObjects ) use ( $output , $index , $type , & $lastStep , & $current ) {
if ( $increment > $totalObjects ) {
$increment = $totalObjects ;
}
$currentTime = microtime ( true );
$timeDifference = $currentTime - $lastStep ;
$objectsPerSecond = $lastStep ? ( $increment / $timeDifference ) : $increment ;
$lastStep = $currentTime ;
$current += $increment ;
$percent = 100 * $current / $totalObjects ;
$output -> writeln ( sprintf (
'<info>Populating</info> <comment>%s/%s</comment> %0.1f%% (%d/%d), %d objects/s (RAM: current=%uMo peak=%uMo)' ,
$index ,
$type ,
$percent ,
$current ,
$totalObjects ,
$objectsPerSecond ,
round ( memory_get_usage () / ( 1024 * 1024 )),
round ( memory_get_peak_usage () / ( 1024 * 1024 ))
));
};
}
ProgressBar :: setFormatDefinition ( 'normal' , " %current%/%max% [%bar%] %percent:3s%% \n %message% " );
ProgressBar :: setFormatDefinition ( 'verbose' , " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s% \n %message% " );
ProgressBar :: setFormatDefinition ( 'very_verbose' , " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% \n %message% " );
ProgressBar :: setFormatDefinition ( 'debug' , " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s% \n %message% " );
$progress = null ;
return function ( $increment , $totalObjects ) use ( & $progress , $output , $index , $type ) {
if ( null === $progress ) {
$progress = new ProgressBar ( $output , $totalObjects );
}
$progress -> setMessage ( sprintf ( '<info>Populating</info> <comment>%s/%s</comment>' , $index , $type ));
$progress -> advance ( $increment );
if ( $progress -> getProgress () >= $progress -> getMaxSteps ()) {
$progress -> finish ();
}
};
}
2012-03-12 17:02:25 +01:00
/**
* Recreates an index , populates its types , and refreshes the index .
*
* @ param OutputInterface $output
* @ param string $index
2012-06-13 17:52:34 +02:00
* @ param boolean $reset
2013-10-08 12:00:04 +02:00
* @ param array $options
2012-03-12 17:02:25 +01:00
*/
2013-10-08 12:00:04 +02:00
private function populateIndex ( OutputInterface $output , $index , $reset , $options )
2012-03-12 17:02:25 +01:00
{
2014-04-02 23:00:52 +02:00
if ( $reset ) {
2012-09-19 12:48:05 +02:00
$output -> writeln ( sprintf ( '<info>Resetting</info> <comment>%s</comment>' , $index ));
2014-06-27 07:08:08 +02:00
$this -> resetter -> resetIndex ( $index , true );
2012-06-13 18:08:08 +02:00
}
2012-03-12 17:02:25 +01:00
2015-01-22 01:18:51 +01:00
/** @var $providers ProviderInterface[] */
$providers = $this -> providerRegistry -> getIndexProviders ( $index );
2015-01-07 18:42:15 +01:00
2015-01-22 01:18:51 +01:00
foreach ( $providers as $type => $provider ) {
$this -> doPopulateType ( $provider , $output , $index , $type , $options );
2012-03-12 17:02:25 +01:00
}
2015-01-22 01:18:51 +01:00
$this -> refreshIndex ( $output , $index );
2012-03-12 17:02:25 +01:00
}
/**
* Deletes / remaps an index type , populates it , and refreshes the index .
*
* @ param OutputInterface $output
* @ param string $index
* @ param string $type
2012-06-13 17:52:34 +02:00
* @ param boolean $reset
2013-10-08 12:00:04 +02:00
* @ param array $options
2012-03-12 17:02:25 +01:00
*/
2013-10-08 12:00:04 +02:00
private function populateIndexType ( OutputInterface $output , $index , $type , $reset , $options )
2012-03-12 17:02:25 +01:00
{
2012-06-13 17:52:34 +02:00
if ( $reset ) {
2013-06-18 09:52:44 +02:00
$output -> writeln ( sprintf ( '<info>Resetting</info> <comment>%s/%s</comment>' , $index , $type ));
2012-05-07 18:10:26 +02:00
$this -> resetter -> resetIndexType ( $index , $type );
}
2011-04-12 04:27:47 +02:00
2012-03-12 17:02:25 +01:00
$provider = $this -> providerRegistry -> getProvider ( $index , $type );
2015-01-22 01:18:51 +01:00
$this -> doPopulateType ( $provider , $output , $index , $type , $options );
$this -> refreshIndex ( $output , $index , false );
}
/**
* Refreshes an index .
*
* @ param OutputInterface $output
* @ param string $index
* @ param bool $postPopulate
*/
private function refreshIndex ( OutputInterface $output , $index , $postPopulate = true )
{
if ( $postPopulate ) {
$this -> resetter -> postPopulate ( $index );
}
2011-09-12 18:28:59 +02:00
2013-06-18 09:52:44 +02:00
$output -> writeln ( sprintf ( '<info>Refreshing</info> <comment>%s</comment>' , $index ));
2012-03-12 17:02:25 +01:00
$this -> indexManager -> getIndex ( $index ) -> refresh ();
2011-04-12 04:27:47 +02:00
}
}