diff --git a/CHANGELOG-3.1.md b/CHANGELOG-3.1.md index 9f79d88..478840e 100644 --- a/CHANGELOG-3.1.md +++ b/CHANGELOG-3.1.md @@ -38,3 +38,9 @@ https://github.com/FriendsOfSymfony/FOSElasticaBundle/compare/v3.0.4...v3.1.0 * Added a `SliceFetcher` abstraction for Doctrine providers that get more information about the previous slice allowing for optimising queries during population. #725 + * New events `PRE_INDEX_POPULATE`, `POST_INDEX_POPULATE`, `PRE_TYPE_POPULATE` and + `POST_TYPE_POPULATE` allow for monitoring when an index is about to be or has + just been populated. #744 + * New events `PRE_INDEX_RESET`, `POST_INDEX_RESET`, `PRE_TYPE_RESET` and + `POST_TYPE_RESET` are run before and after operations that will reset an + index. #744 diff --git a/Command/PopulateCommand.php b/Command/PopulateCommand.php index e4ed4c9..ed686d9 100644 --- a/Command/PopulateCommand.php +++ b/Command/PopulateCommand.php @@ -2,6 +2,9 @@ namespace FOS\ElasticaBundle\Command; +use FOS\ElasticaBundle\Event\IndexPopulateEvent; +use FOS\ElasticaBundle\Event\PopulateEvent; +use FOS\ElasticaBundle\Event\TypePopulateEvent; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Helper\DialogHelper; use Symfony\Component\Console\Input\InputOption; @@ -10,7 +13,6 @@ use Symfony\Component\Console\Output\OutputInterface; use FOS\ElasticaBundle\IndexManager; use FOS\ElasticaBundle\Provider\ProviderRegistry; use FOS\ElasticaBundle\Resetter; -use FOS\ElasticaBundle\Provider\ProviderInterface; use Symfony\Component\Console\Helper\ProgressBar; /** @@ -18,6 +20,11 @@ use Symfony\Component\Console\Helper\ProgressBar; */ class PopulateCommand extends ContainerAwareCommand { + /** + * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface + */ + private $dispatcher; + /** * @var IndexManager */ @@ -62,6 +69,7 @@ class PopulateCommand extends ContainerAwareCommand */ protected function initialize(InputInterface $input, OutputInterface $output) { + $this->dispatcher = $this->getContainer()->get('event_dispatcher'); $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'); @@ -113,20 +121,6 @@ class PopulateCommand extends ContainerAwareCommand } } - /** - * @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->progressClosureBuilder->build($output, 'Populating', $input, $type); - - $provider->populate($loggerClosure, $options); - } - /** * Recreates an index, populates its types, and refreshes the index. * @@ -137,18 +131,21 @@ class PopulateCommand extends ContainerAwareCommand */ private function populateIndex(OutputInterface $output, $index, $reset, $options) { - if ($reset) { + $event = new IndexPopulateEvent($index, $reset, $options); + $this->dispatcher->dispatch(IndexPopulateEvent::PRE_INDEX_POPULATE, $event); + + if ($event->isReset()) { $output->writeln(sprintf('Resetting %s', $index)); $this->resetter->resetIndex($index, true); } - /** @var $providers ProviderInterface[] */ - $providers = $this->providerRegistry->getIndexProviders($index); - - foreach ($providers as $type => $provider) { - $this->doPopulateType($provider, $output, $index, $type, $options); + $types = array_keys($this->providerRegistry->getIndexProviders($index)); + foreach ($types as $type) { + $this->populateIndexType($output, $index, $type, false, $event->getOptions()); } + $this->dispatcher->dispatch(IndexPopulateEvent::POST_INDEX_POPULATE, $event); + $this->refreshIndex($output, $index); } @@ -163,13 +160,19 @@ class PopulateCommand extends ContainerAwareCommand */ private function populateIndexType(OutputInterface $output, $index, $type, $reset, $options) { - if ($reset) { + $event = new TypePopulateEvent($index, $type, $reset, $options); + $this->dispatcher->dispatch(TypePopulateEvent::PRE_TYPE_POPULATE, $event); + + if ($event->isReset()) { $output->writeln(sprintf('Resetting %s/%s', $index, $type)); $this->resetter->resetIndexType($index, $type); } $provider = $this->providerRegistry->getProvider($index, $type); - $this->doPopulateType($provider, $output, $index, $type, $options); + $loggerClosure = $this->getLoggerClosure($output, $index, $type); + $provider->populate($loggerClosure, $event->getOptions()); + + $this->dispatcher->dispatch(TypePopulateEvent::POST_TYPE_POPULATE, $event); $this->refreshIndex($output, $index, false); } diff --git a/Event/IndexPopulateEvent.php b/Event/IndexPopulateEvent.php new file mode 100644 index 0000000..56b1e83 --- /dev/null +++ b/Event/IndexPopulateEvent.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FOS\ElasticaBundle\Event; + +use Symfony\Component\EventDispatcher\Event; + +/** + * Index Populate Event + * + * @author Oleg Andreyev + */ +class IndexPopulateEvent extends Event +{ + const PRE_INDEX_POPULATE = 'elastica.index.index_pre_populate'; + const POST_INDEX_POPULATE = 'elastica.index.index_post_populate'; + + /** + * @var string + */ + private $index; + + /** + * @var bool + */ + private $reset; + + /** + * @var array + */ + private $options; + + /** + * @param string $index + * @param boolean $reset + * @param array $options + */ + public function __construct($index, $reset, $options) + { + $this->index = $index; + $this->reset = $reset; + $this->options = $options; + } + + /** + * @return string + */ + public function getIndex() + { + return $this->index; + } + + /** + * @return boolean + */ + public function isReset() + { + return $this->reset; + } + + /** + * @return array + */ + public function getOptions() + { + return $this->options; + } + + /** + * @param boolean $reset + */ + public function setReset($reset) + { + $this->reset = $reset; + } +} diff --git a/Event/IndexResetEvent.php b/Event/IndexResetEvent.php new file mode 100644 index 0000000..0caf241 --- /dev/null +++ b/Event/IndexResetEvent.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FOS\ElasticaBundle\Event; + +use Symfony\Component\EventDispatcher\Event; + +/** + * Index ResetEvent + * + * @author Oleg Andreyev + */ +class IndexResetEvent extends Event +{ + const PRE_INDEX_RESET = 'elastica.index.pre_reset'; + const POST_INDEX_RESET = 'elastica.index.post_reset'; + + /** + * @var bool + */ + private $force; + + /** + * @var string + */ + private $index; + + /** + * @var bool + */ + private $populating; + + /** + * @param string $index + * @param bool $populating + * @param bool $force + */ + public function __construct($index, $populating, $force) + { + $this->force = $force; + $this->index = $index; + $this->populating = $populating; + } + + /** + * @return string + */ + public function getIndex() + { + return $this->index; + } + + /** + * @return boolean + */ + public function isForce() + { + return $this->force; + } + + /** + * @return boolean + */ + public function isPopulating() + { + return $this->populating; + } + + /** + * @param boolean $force + */ + public function setForce($force) + { + $this->force = $force; + } +} diff --git a/Event/TypePopulateEvent.php b/Event/TypePopulateEvent.php new file mode 100644 index 0000000..e04bdd8 --- /dev/null +++ b/Event/TypePopulateEvent.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FOS\ElasticaBundle\Event; + +use Symfony\Component\EventDispatcher\Event; + +/** + * Type Populate Event + * + * @author Oleg Andreyev + */ +class TypePopulateEvent extends IndexPopulateEvent +{ + const PRE_TYPE_POPULATE = 'elastica.index.type_pre_populate'; + const POST_TYPE_POPULATE = 'elastica.index.type_post_populate'; + + /** + * @var string + */ + private $type; + + /** + * @param string $index + * @param string $type + * @param bool $reset + * @param array $options + */ + public function __construct($index, $type, $reset, $options) + { + parent::__construct($index, $reset, $options); + + $this->type = $type; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } +} diff --git a/Event/TypeResetEvent.php b/Event/TypeResetEvent.php new file mode 100644 index 0000000..37c2cf8 --- /dev/null +++ b/Event/TypeResetEvent.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FOS\ElasticaBundle\Event; + +use Symfony\Component\EventDispatcher\Event; + +/** + * Type ResetEvent + * + * @author Oleg Andreyev + */ +class TypeResetEvent extends Event +{ + const PRE_TYPE_RESET = 'elastica.index.type_pre_reset'; + const POST_TYPE_RESET = 'elastica.index.type_post_reset'; + + /** + * @var string + */ + private $index; + + /** + * @var string + */ + private $type; + + /** + * @param string $index + * @param string $type + */ + public function __construct($index, $type) + { + $this->type = $type; + $this->index = $index; + } + + /** + * @return string + */ + public function getIndex() + { + return $this->index; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } +} diff --git a/Index/Resetter.php b/Index/Resetter.php index 68a43dd..1eb91a5 100644 --- a/Index/Resetter.php +++ b/Index/Resetter.php @@ -6,6 +6,9 @@ use Elastica\Index; use Elastica\Exception\ResponseException; use Elastica\Type\Mapping; use FOS\ElasticaBundle\Configuration\ConfigManager; +use FOS\ElasticaBundle\Event\IndexResetEvent; +use FOS\ElasticaBundle\Event\TypeResetEvent; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Deletes and recreates indexes @@ -18,10 +21,15 @@ class Resetter private $aliasProcessor; /*** - * @var \FOS\ElasticaBundle\Configuration\Manager + * @var ConfigManager */ private $configManager; + /** + * @var EventDispatcherInterface + */ + private $dispatcher; + /** * @var IndexManager */ @@ -32,10 +40,23 @@ class Resetter */ private $mappingBuilder; - public function __construct(ConfigManager $configManager, IndexManager $indexManager, AliasProcessor $aliasProcessor, MappingBuilder $mappingBuilder) - { + /** + * @param ConfigManager $configManager + * @param IndexManager $indexManager + * @param AliasProcessor $aliasProcessor + * @param MappingBuilder $mappingBuilder + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct( + ConfigManager $configManager, + IndexManager $indexManager, + AliasProcessor $aliasProcessor, + MappingBuilder $mappingBuilder, + EventDispatcherInterface $eventDispatcher + ) { $this->aliasProcessor = $aliasProcessor; $this->configManager = $configManager; + $this->dispatcher = $eventDispatcher; $this->indexManager = $indexManager; $this->mappingBuilder = $mappingBuilder; } @@ -64,6 +85,9 @@ class Resetter */ public function resetIndex($indexName, $populating = false, $force = false) { + $event = new IndexResetEvent($indexName, $populating, $force); + $this->dispatcher->dispatch(IndexResetEvent::PRE_INDEX_RESET, $event); + $indexConfig = $this->configManager->getIndexConfiguration($indexName); $index = $this->indexManager->getIndex($indexName); @@ -77,6 +101,8 @@ class Resetter if (!$populating and $indexConfig->isUseAlias()) { $this->aliasProcessor->switchIndexAlias($indexConfig, $index, $force); } + + $this->dispatcher->dispatch(IndexResetEvent::POST_INDEX_RESET, $event); } /** @@ -89,6 +115,9 @@ class Resetter */ public function resetIndexType($indexName, $typeName) { + $event = new TypeResetEvent($indexName, $typeName); + $this->dispatcher->dispatch(TypeResetEvent::PRE_TYPE_RESET, $event); + $typeConfig = $this->configManager->getTypeConfiguration($indexName, $typeName); $type = $this->indexManager->getIndex($indexName)->getType($typeName); @@ -100,12 +129,14 @@ class Resetter } } - $mapping = new Mapping; + $mapping = new Mapping(); foreach ($this->mappingBuilder->buildTypeMapping($typeConfig) as $name => $field) { $mapping->setParam($name, $field); } $type->setMapping($mapping); + + $this->dispatcher->dispatch(TypeResetEvent::POST_TYPE_RESET, $event); } /** diff --git a/Provider/ProviderRegistry.php b/Provider/ProviderRegistry.php index 2142223..389d972 100644 --- a/Provider/ProviderRegistry.php +++ b/Provider/ProviderRegistry.php @@ -58,7 +58,7 @@ class ProviderRegistry implements ContainerAwareInterface * Providers will be indexed by "type" strings in the returned array. * * @param string $index - * @return array of ProviderInterface instances + * @return ProviderInterface[] * @throws \InvalidArgumentException if no providers were registered for the index */ public function getIndexProviders($index) diff --git a/Resources/config/index.xml b/Resources/config/index.xml index 11586ff..3ae2e50 100644 --- a/Resources/config/index.xml +++ b/Resources/config/index.xml @@ -41,6 +41,7 @@ + diff --git a/Tests/Index/ResetterTest.php b/Tests/Index/ResetterTest.php index 28f0a68..35a0bd9 100644 --- a/Tests/Index/ResetterTest.php +++ b/Tests/Index/ResetterTest.php @@ -36,8 +36,11 @@ class ResetterTest extends \PHPUnit_Framework_TestCase $this->mappingBuilder = $this->getMockBuilder('FOS\\ElasticaBundle\\Index\\MappingBuilder') ->disableOriginalConstructor() ->getMock(); + $this->resetter = $this->getMockBuilder('FOS\ElasticaBundle\Index\Resetter') + ->disableOriginalConstructor() + ->getMock(); - $this->resetter = new Resetter($this->configManager, $this->indexManager, $this->aliasProcessor, $this->mappingBuilder); + $this->resetter = new Resetter($this->configManager, $this->indexManager, $this->aliasProcessor, $this->mappingBuilder, $this->resetter); /*$this->indexConfigsByName = array( 'foo' => array(