From 4c961a757d8b9cca38e1312f196f0a766192fb88 Mon Sep 17 00:00:00 2001 From: Tim Nagel Date: Mon, 21 Apr 2014 09:21:50 +1000 Subject: [PATCH] Deprecate top level classes --- CHANGELOG-3.0.md | 14 +- Client.php | 38 +-- DynamicIndex.php | 22 +- Elastica/LoggingClient.php | 47 ++++ Elastica/TransformingIndex.php | 45 ++++ Index/IndexManager.php | 63 +++++ Index/Resetter.php | 246 ++++++++++++++++++ IndexManager.php | 61 +---- Resetter.php | 238 +---------------- Resources/config/config.xml | 4 +- .../LoggingClientTest.php} | 6 +- Tests/{ => Index}/IndexManagerTest.php | 4 +- Tests/{ => Index}/ResetterTest.php | 4 +- 13 files changed, 436 insertions(+), 356 deletions(-) create mode 100644 Elastica/LoggingClient.php create mode 100644 Elastica/TransformingIndex.php create mode 100644 Index/IndexManager.php create mode 100644 Index/Resetter.php rename Tests/{ClientTest.php => Elastica/LoggingClientTest.php} (86%) rename Tests/{ => Index}/IndexManagerTest.php (95%) rename Tests/{ => Index}/ResetterTest.php (98%) diff --git a/CHANGELOG-3.0.md b/CHANGELOG-3.0.md index abd05cd..e57fb4d 100644 --- a/CHANGELOG-3.0.md +++ b/CHANGELOG-3.0.md @@ -12,7 +12,19 @@ https://github.com/FriendsOfSymfony/FOSElasticaBundle/compare/v3.0.0...v3.0.1 To generate a changelog summary since the last version, run `git log --no-merges --oneline v3.0.0...3.0.x` -* 3.0.0-ALPHA3 (xxxx-xx-xx) +* 3.0.0 + + * Deprecated FOS\ElasticaBundle\Client in favour of FOS\ElasticaBundle\Elastica\LoggingClient + * Deprecated FOS\ElasticaBundle\DynamicIndex in favour of FOS\ElasticaBundle\Elastica\TransformingIndex + * Deprecated FOS\ElasticaBundle\IndexManager in favour of FOS\ElasticaBundle\Index\IndexManager + * Deprecated FOS\ElasticaBundle\Resetter in favour of FOS\ElasticaBundle\Index\Resetter + +* 3.0.0-ALPHA4 (2014-04-10) + + * Indexes are now capable of logging errors with Elastica + * Fixed deferred indexing of deleted documents + +* 3.0.0-ALPHA3 (2014-04-01) * a9c4c93: Logger is now only enabled in debug mode by default * #463: allowing hot swappable reindexing diff --git a/Client.php b/Client.php index 3eb98fe..f85756d 100644 --- a/Client.php +++ b/Client.php @@ -2,43 +2,11 @@ namespace FOS\ElasticaBundle; -use Elastica\Client as ElasticaClient; -use Elastica\Request; -use FOS\ElasticaBundle\Logger\ElasticaLogger; +use FOS\ElasticaBundle\Elastica\LoggingClient; /** - * @author Gordon Franke + * @deprecated Use \FOS\ElasticaBundle\Elastica\LoggingClient */ -class Client extends ElasticaClient +class Client extends LoggingClient { - /** - * {@inheritdoc} - */ - public function request($path, $method = Request::GET, $data = array(), array $query = array()) - { - $start = microtime(true); - $response = parent::request($path, $method, $data, $query); - - if (null !== $this->_logger and $this->_logger instanceof ElasticaLogger) { - $time = microtime(true) - $start; - - $connection = $this->getLastRequest()->getConnection(); - - $connection_array = array( - 'host' => $connection->getHost(), - 'port' => $connection->getPort(), - 'transport' => $connection->getTransport(), - 'headers' => $connection->getConfig('headers'), - ); - - $this->_logger->logQuery($path, $method, $data, $time, $connection_array, $query); - } - - return $response; - } - - public function getIndex($name) - { - return new DynamicIndex($this, $name); - } } diff --git a/DynamicIndex.php b/DynamicIndex.php index cbec8e9..992f650 100644 --- a/DynamicIndex.php +++ b/DynamicIndex.php @@ -2,27 +2,11 @@ namespace FOS\ElasticaBundle; -use Elastica\Index; +use FOS\ElasticaBundle\Elastica\TransformingIndex; /** - * Elastica index capable of reassigning name dynamically - * - * @author Konstantin Tjuterev + * @deprecated Use \FOS\ElasticaBundle\Elastica\TransformingIndex */ -class DynamicIndex extends Index +class DynamicIndex extends TransformingIndex { - /** - * Reassign index name - * - * While it's technically a regular setter for name property, it's specifically named overrideName, but not setName - * since it's used for a very specific case and normally should not be used - * - * @param string $name Index name - * - * @return void - */ - public function overrideName($name) - { - $this->_name = $name; - } } diff --git a/Elastica/LoggingClient.php b/Elastica/LoggingClient.php new file mode 100644 index 0000000..0ff1997 --- /dev/null +++ b/Elastica/LoggingClient.php @@ -0,0 +1,47 @@ + + */ +class LoggingClient extends Client +{ + /** + * {@inheritdoc} + */ + public function request($path, $method = Request::GET, $data = array(), array $query = array()) + { + $start = microtime(true); + $response = parent::request($path, $method, $data, $query); + + if (null !== $this->_logger and $this->_logger instanceof ElasticaLogger) { + $time = microtime(true) - $start; + + $connection = $this->getLastRequest()->getConnection(); + + $connection_array = array( + 'host' => $connection->getHost(), + 'port' => $connection->getPort(), + 'transport' => $connection->getTransport(), + 'headers' => $connection->getConfig('headers'), + ); + + $this->_logger->logQuery($path, $method, $data, $time, $connection_array, $query); + } + + return $response; + } + + public function getIndex($name) + { + return new DynamicIndex($this, $name); + } +} diff --git a/Elastica/TransformingIndex.php b/Elastica/TransformingIndex.php new file mode 100644 index 0000000..a0cc001 --- /dev/null +++ b/Elastica/TransformingIndex.php @@ -0,0 +1,45 @@ + + * @author Tim Nagel + */ +class TransformingIndex extends Index +{ + /** + * Indexes a + * @param string $query + * @param int|array $options + * @return \Elastica\Search + */ + public function createSearch($query = '', $options = null) + { + $search = new Search($this->getClient()); + $search->addIndex($this); + $search->setOptionsAndQuery($options, $query); + + return $search; + } + + /** + * Reassign index name + * + * While it's technically a regular setter for name property, it's specifically named overrideName, but not setName + * since it's used for a very specific case and normally should not be used + * + * @param string $name Index name + * + * @return void + */ + public function overrideName($name) + { + $this->_name = $name; + } +} diff --git a/Index/IndexManager.php b/Index/IndexManager.php new file mode 100644 index 0000000..543ccae --- /dev/null +++ b/Index/IndexManager.php @@ -0,0 +1,63 @@ +indexesByName = $indexesByName; + $this->defaultIndexName = $defaultIndex->getName(); + } + + /** + * Gets all registered indexes + * + * @return array + */ + public function getAllIndexes() + { + return $this->indexesByName; + } + + /** + * Gets an index by its name + * + * @param string $name Index to return, or the default index if null + * @return Index + * @throws \InvalidArgumentException if no index exists for the given name + */ + public function getIndex($name = null) + { + if (null === $name) { + $name = $this->defaultIndexName; + } + + if (!isset($this->indexesByName[$name])) { + throw new \InvalidArgumentException(sprintf('The index "%s" does not exist', $name)); + } + + return $this->indexesByName[$name]; + } + + /** + * Gets the default index + * + * @return Index + */ + public function getDefaultIndex() + { + return $this->getIndex($this->defaultIndexName); + } +} diff --git a/Index/Resetter.php b/Index/Resetter.php new file mode 100644 index 0000000..1151ed7 --- /dev/null +++ b/Index/Resetter.php @@ -0,0 +1,246 @@ +indexConfigsByName = $indexConfigsByName; + } + + /** + * Deletes and recreates all indexes + */ + public function resetAllIndexes() + { + foreach (array_keys($this->indexConfigsByName) as $name) { + $this->resetIndex($name); + } + } + + /** + * Deletes and recreates the named index + * + * @param string $indexName + * @throws \InvalidArgumentException if no index exists for the given name + */ + public function resetIndex($indexName) + { + $indexConfig = $this->getIndexConfig($indexName); + $esIndex = $indexConfig['index']; + if (isset($indexConfig['use_alias']) && $indexConfig['use_alias']) { + $name = $indexConfig['name_or_alias']; + $name .= uniqid(); + $esIndex->overrideName($name); + $esIndex->create($indexConfig['config']); + + return; + } + + $esIndex->create($indexConfig['config'], true); + } + + /** + * Deletes and recreates a mapping type for the named index + * + * @param string $indexName + * @param string $typeName + * @throws \InvalidArgumentException if no index or type mapping exists for the given names + * @throws ResponseException + */ + public function resetIndexType($indexName, $typeName) + { + $indexConfig = $this->getIndexConfig($indexName); + + if (!isset($indexConfig['config']['mappings'][$typeName]['properties'])) { + throw new \InvalidArgumentException(sprintf('The mapping for index "%s" and type "%s" does not exist.', $indexName, $typeName)); + } + + $type = $indexConfig['index']->getType($typeName); + try { + $type->delete(); + } catch (ResponseException $e) { + if (strpos($e->getMessage(), 'TypeMissingException') === false) { + throw $e; + } + } + $mapping = $this->createMapping($indexConfig['config']['mappings'][$typeName]); + $type->setMapping($mapping); + } + + /** + * create type mapping object + * + * @param array $indexConfig + * @return Mapping + */ + protected function createMapping($indexConfig) + { + $mapping = Mapping::create($indexConfig['properties']); + + $mappingSpecialFields = array('_uid', '_id', '_source', '_all', '_analyzer', '_boost', '_routing', '_index', '_size', '_timestamp', '_ttl', 'dynamic_templates'); + foreach ($mappingSpecialFields as $specialField) { + if (isset($indexConfig[$specialField])) { + $mapping->setParam($specialField, $indexConfig[$specialField]); + } + } + + if (isset($indexConfig['_parent'])) { + $mapping->setParam('_parent', array('type' => $indexConfig['_parent']['type'])); + } + + return $mapping; + } + + /** + * Gets an index config by its name + * + * @param string $indexName Index name + * + * @param $indexName + * @return array + * @throws \InvalidArgumentException if no index config exists for the given name + */ + protected function getIndexConfig($indexName) + { + if (!isset($this->indexConfigsByName[$indexName])) { + throw new \InvalidArgumentException(sprintf('The configuration for index "%s" does not exist.', $indexName)); + } + + return $this->indexConfigsByName[$indexName]; + } + + public function postPopulate($indexName) + { + $indexConfig = $this->getIndexConfig($indexName); + if (isset($indexConfig['use_alias']) && $indexConfig['use_alias']) { + $this->switchIndexAlias($indexName); + } + } + + /** + * Switches the alias for given index (by key) to the newly populated index + * and deletes the old index + * + * @param string $indexName Index name + * + * @throws \RuntimeException + */ + private function switchIndexAlias($indexName) + { + $indexConfig = $this->getIndexConfig($indexName); + $esIndex = $indexConfig['index']; + $aliasName = $indexConfig['name_or_alias']; + $oldIndexName = false; + $newIndexName = $esIndex->getName(); + + $aliasedIndexes = $this->getAliasedIndexes($esIndex, $aliasName); + + if (count($aliasedIndexes) > 1) { + throw new \RuntimeException( + sprintf( + 'Alias %s is used for multiple indexes: [%s]. + Make sure it\'s either not used or is assigned to one index only', + $aliasName, + join(', ', $aliasedIndexes) + ) + ); + } + + // Change the alias to point to the new index + // Elastica's addAlias can't be used directly, because in current (0.19.x) version it's not atomic + // In 0.20.x it's atomic, but it doesn't return the old index name + $aliasUpdateRequest = array('actions' => array()); + if (count($aliasedIndexes) == 1) { + // if the alias is set - add an action to remove it + $oldIndexName = $aliasedIndexes[0]; + $aliasUpdateRequest['actions'][] = array( + 'remove' => array('index' => $oldIndexName, 'alias' => $aliasName) + ); + } + + // add an action to point the alias to the new index + $aliasUpdateRequest['actions'][] = array( + 'add' => array('index' => $newIndexName, 'alias' => $aliasName) + ); + + try { + $esIndex->getClient()->request('_aliases', 'POST', $aliasUpdateRequest); + } catch (ExceptionInterface $renameAliasException) { + $additionalError = ''; + // if we failed to move the alias, delete the newly built index + try { + $esIndex->delete(); + } catch (ExceptionInterface $deleteNewIndexException) { + $additionalError = sprintf( + 'Tried to delete newly built index %s, but also failed: %s', + $newIndexName, + $deleteNewIndexException->getError() + ); + } + + throw new \RuntimeException( + sprintf( + 'Failed to updated index alias: %s. %s', + $renameAliasException->getMessage(), + $additionalError ?: sprintf('Newly built index %s was deleted', $newIndexName) + ) + ); + } + + // Delete the old index after the alias has been switched + if ($oldIndexName) { + $oldIndex = new Index($esIndex->getClient(), $oldIndexName); + try { + $oldIndex->delete(); + } catch (ExceptionInterface $deleteOldIndexException) { + throw new \RuntimeException( + sprintf( + 'Failed to delete old index %s with message: %s', + $oldIndexName, + $deleteOldIndexException->getMessage() + ) + ); + } + } + } + + /** + * Returns array of indexes which are mapped to given alias + * + * @param Index $esIndex ES Index + * @param string $aliasName Alias name + * + * @return array + */ + private function getAliasedIndexes(Index $esIndex, $aliasName) + { + $aliasesInfo = $esIndex->getClient()->request('_aliases', 'GET')->getData(); + $aliasedIndexes = array(); + + foreach ($aliasesInfo as $indexName => $indexInfo) { + $aliases = array_keys($indexInfo['aliases']); + if (in_array($aliasName, $aliases)) { + $aliasedIndexes[] = $indexName; + } + } + + return $aliasedIndexes; + } +} diff --git a/IndexManager.php b/IndexManager.php index e20a791..e7c74c8 100644 --- a/IndexManager.php +++ b/IndexManager.php @@ -2,62 +2,11 @@ namespace FOS\ElasticaBundle; -use Elastica\Index; +use FOS\ElasticaBundle\Index\IndexManager as BaseIndexManager; -class IndexManager +/** + * @deprecated Use \FOS\ElasticaBundle\Index\IndexManager + */ +class IndexManager extends BaseIndexManager { - protected $indexesByName; - protected $defaultIndexName; - - /** - * Constructor. - * - * @param array $indexesByName - * @param Index $defaultIndex - */ - public function __construct(array $indexesByName, Index $defaultIndex) - { - $this->indexesByName = $indexesByName; - $this->defaultIndexName = $defaultIndex->getName(); - } - - /** - * Gets all registered indexes - * - * @return array - */ - public function getAllIndexes() - { - return $this->indexesByName; - } - - /** - * Gets an index by its name - * - * @param string $name Index to return, or the default index if null - * @return Index - * @throws \InvalidArgumentException if no index exists for the given name - */ - public function getIndex($name = null) - { - if (null === $name) { - $name = $this->defaultIndexName; - } - - if (!isset($this->indexesByName[$name])) { - throw new \InvalidArgumentException(sprintf('The index "%s" does not exist', $name)); - } - - return $this->indexesByName[$name]; - } - - /** - * Gets the default index - * - * @return Index - */ - public function getDefaultIndex() - { - return $this->getIndex($this->defaultIndexName); - } } diff --git a/Resetter.php b/Resetter.php index fe963d0..dd24451 100644 --- a/Resetter.php +++ b/Resetter.php @@ -2,245 +2,11 @@ namespace FOS\ElasticaBundle; -use Elastica\Exception\ExceptionInterface; -use Elastica\Index; -use Elastica\Exception\ResponseException; -use Elastica\Type\Mapping; +use FOS\ElasticaBundle\Index\Resetter as BaseResetter; /** * Deletes and recreates indexes */ -class Resetter +class Resetter extends BaseResetter { - protected $indexConfigsByName; - - /** - * Constructor. - * - * @param array $indexConfigsByName - */ - public function __construct(array $indexConfigsByName) - { - $this->indexConfigsByName = $indexConfigsByName; - } - - /** - * Deletes and recreates all indexes - */ - public function resetAllIndexes() - { - foreach (array_keys($this->indexConfigsByName) as $name) { - $this->resetIndex($name); - } - } - - /** - * Deletes and recreates the named index - * - * @param string $indexName - * @throws \InvalidArgumentException if no index exists for the given name - */ - public function resetIndex($indexName) - { - $indexConfig = $this->getIndexConfig($indexName); - $esIndex = $indexConfig['index']; - if (isset($indexConfig['use_alias']) && $indexConfig['use_alias']) { - $name = $indexConfig['name_or_alias']; - $name .= uniqid(); - $esIndex->overrideName($name); - $esIndex->create($indexConfig['config']); - - return; - } - - $esIndex->create($indexConfig['config'], true); - } - - /** - * Deletes and recreates a mapping type for the named index - * - * @param string $indexName - * @param string $typeName - * @throws \InvalidArgumentException if no index or type mapping exists for the given names - * @throws ResponseException - */ - public function resetIndexType($indexName, $typeName) - { - $indexConfig = $this->getIndexConfig($indexName); - - if (!isset($indexConfig['config']['mappings'][$typeName]['properties'])) { - throw new \InvalidArgumentException(sprintf('The mapping for index "%s" and type "%s" does not exist.', $indexName, $typeName)); - } - - $type = $indexConfig['index']->getType($typeName); - try { - $type->delete(); - } catch (ResponseException $e) { - if (strpos($e->getMessage(), 'TypeMissingException') === false) { - throw $e; - } - } - $mapping = $this->createMapping($indexConfig['config']['mappings'][$typeName]); - $type->setMapping($mapping); - } - - /** - * create type mapping object - * - * @param array $indexConfig - * @return Mapping - */ - protected function createMapping($indexConfig) - { - $mapping = Mapping::create($indexConfig['properties']); - - $mappingSpecialFields = array('_uid', '_id', '_source', '_all', '_analyzer', '_boost', '_routing', '_index', '_size', '_timestamp', '_ttl', 'dynamic_templates'); - foreach ($mappingSpecialFields as $specialField) { - if (isset($indexConfig[$specialField])) { - $mapping->setParam($specialField, $indexConfig[$specialField]); - } - } - - if (isset($indexConfig['_parent'])) { - $mapping->setParam('_parent', array('type' => $indexConfig['_parent']['type'])); - } - - return $mapping; - } - - /** - * Gets an index config by its name - * - * @param string $indexName Index name - * - * @param $indexName - * @return array - * @throws \InvalidArgumentException if no index config exists for the given name - */ - protected function getIndexConfig($indexName) - { - if (!isset($this->indexConfigsByName[$indexName])) { - throw new \InvalidArgumentException(sprintf('The configuration for index "%s" does not exist.', $indexName)); - } - - return $this->indexConfigsByName[$indexName]; - } - - public function postPopulate($indexName) - { - $indexConfig = $this->getIndexConfig($indexName); - if (isset($indexConfig['use_alias']) && $indexConfig['use_alias']) { - $this->switchIndexAlias($indexName); - } - } - - /** - * Switches the alias for given index (by key) to the newly populated index - * and deletes the old index - * - * @param string $indexName Index name - * - * @throws \RuntimeException - */ - private function switchIndexAlias($indexName) - { - $indexConfig = $this->getIndexConfig($indexName); - $esIndex = $indexConfig['index']; - $aliasName = $indexConfig['name_or_alias']; - $oldIndexName = false; - $newIndexName = $esIndex->getName(); - - $aliasedIndexes = $this->getAliasedIndexes($esIndex, $aliasName); - - if (count($aliasedIndexes) > 1) { - throw new \RuntimeException( - sprintf( - 'Alias %s is used for multiple indexes: [%s]. - Make sure it\'s either not used or is assigned to one index only', - $aliasName, - join(', ', $aliasedIndexes) - ) - ); - } - - // Change the alias to point to the new index - // Elastica's addAlias can't be used directly, because in current (0.19.x) version it's not atomic - // In 0.20.x it's atomic, but it doesn't return the old index name - $aliasUpdateRequest = array('actions' => array()); - if (count($aliasedIndexes) == 1) { - // if the alias is set - add an action to remove it - $oldIndexName = $aliasedIndexes[0]; - $aliasUpdateRequest['actions'][] = array( - 'remove' => array('index' => $oldIndexName, 'alias' => $aliasName) - ); - } - - // add an action to point the alias to the new index - $aliasUpdateRequest['actions'][] = array( - 'add' => array('index' => $newIndexName, 'alias' => $aliasName) - ); - - try { - $esIndex->getClient()->request('_aliases', 'POST', $aliasUpdateRequest); - } catch (ExceptionInterface $renameAliasException) { - $additionalError = ''; - // if we failed to move the alias, delete the newly built index - try { - $esIndex->delete(); - } catch (ExceptionInterface $deleteNewIndexException) { - $additionalError = sprintf( - 'Tried to delete newly built index %s, but also failed: %s', - $newIndexName, - $deleteNewIndexException->getError() - ); - } - - throw new \RuntimeException( - sprintf( - 'Failed to updated index alias: %s. %s', - $renameAliasException->getMessage(), - $additionalError ?: sprintf('Newly built index %s was deleted', $newIndexName) - ) - ); - } - - // Delete the old index after the alias has been switched - if ($oldIndexName) { - $oldIndex = new Index($esIndex->getClient(), $oldIndexName); - try { - $oldIndex->delete(); - } catch (ExceptionInterface $deleteOldIndexException) { - throw new \RuntimeException( - sprintf( - 'Failed to delete old index %s with message: %s', - $oldIndexName, - $deleteOldIndexException->getMessage() - ) - ); - } - } - } - - /** - * Returns array of indexes which are mapped to given alias - * - * @param Index $esIndex ES Index - * @param string $aliasName Alias name - * - * @return array - */ - private function getAliasedIndexes(Index $esIndex, $aliasName) - { - $aliasesInfo = $esIndex->getClient()->request('_aliases', 'GET')->getData(); - $aliasedIndexes = array(); - - foreach ($aliasesInfo as $indexName => $indexInfo) { - $aliases = array_keys($indexInfo['aliases']); - if (in_array($aliasName, $aliases)) { - $aliasedIndexes[] = $indexName; - } - } - - return $aliasedIndexes; - } } diff --git a/Resources/config/config.xml b/Resources/config/config.xml index c10568d..fbf6d1c 100644 --- a/Resources/config/config.xml +++ b/Resources/config/config.xml @@ -5,8 +5,8 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - FOS\ElasticaBundle\Client - FOS\ElasticaBundle\DynamicIndex + FOS\ElasticaBundle\Elastica\LoggingClient + FOS\ElasticaBundle\Elastica\TransformingIndex Elastica\Type FOS\ElasticaBundle\IndexManager FOS\ElasticaBundle\Resetter diff --git a/Tests/ClientTest.php b/Tests/Elastica/LoggingClientTest.php similarity index 86% rename from Tests/ClientTest.php rename to Tests/Elastica/LoggingClientTest.php index 8a9d91a..b08a2cf 100644 --- a/Tests/ClientTest.php +++ b/Tests/Elastica/LoggingClientTest.php @@ -1,11 +1,11 @@ isType('array') ); - $client = $this->getMockBuilder('FOS\ElasticaBundle\Client') + $client = $this->getMockBuilder('FOS\ElasticaBundle\Elastica\LoggingClient') ->setMethods(array('getConnection')) ->getMock(); diff --git a/Tests/IndexManagerTest.php b/Tests/Index/IndexManagerTest.php similarity index 95% rename from Tests/IndexManagerTest.php rename to Tests/Index/IndexManagerTest.php index 0a8ea37..624f64e 100644 --- a/Tests/IndexManagerTest.php +++ b/Tests/Index/IndexManagerTest.php @@ -1,8 +1,8 @@