-
Notifications
You must be signed in to change notification settings - Fork 25
feature: recreate indexes by swapping them under a common alias #63
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
|
|
||
| namespace CoreShop2VueStorefrontBundle\Bridge; | ||
|
|
||
| use CoreShop2VueStorefrontBundle\Bridge\SwappingIndexService; | ||
| use ONGR\ElasticsearchBundle\Mapping\Converter; | ||
| use ONGR\ElasticsearchBundle\Mapping\IndexSettings; | ||
| use ONGR\ElasticsearchBundle\Service\IndexService; | ||
|
|
@@ -77,7 +78,7 @@ public function __construct(ContainerInterface $container, Converter $converter, | |
| /** | ||
| * @return array<array{persister: PersisterFactory, store: string, language: string, type: string}> | ||
| */ | ||
| public function create(?string $site = null, ?string $type = null, ?string $language = null, ?string $store = null): array | ||
| public function create(?string $site = null, ?string $type = null, ?string $language = null, ?string $store = null, ?string $runTimestamp = null): array | ||
| { | ||
| $options = $this->resolver->resolve(['site' => $site, 'type' => $type, 'language' => $language, 'store' => $store]); | ||
|
|
||
|
|
@@ -115,16 +116,9 @@ public function create(?string $site = null, ?string $type = null, ?string $lang | |
| ]; | ||
|
|
||
| $indexName = $this->inject($this->elasticsearchConfig['index'], $variables); | ||
| $settings = new IndexSettings( | ||
| $className, | ||
| $indexName, | ||
| $indexName, | ||
| $this->elasticsearchConfig['templates'][$className] ?? [], | ||
| $this->inject($this->elasticsearchConfig['hosts'], $variables, true) | ||
| ); | ||
| $indexSettings = new IndexSettings( | ||
| $className, | ||
| $indexName, | ||
| $runTimestamp ? $indexName.'_'.$runTimestamp : $indexName, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better name, maybe |
||
| $indexName, | ||
| array_replace_recursive( | ||
| $indexSettings->getIndexMetadata(), | ||
|
|
@@ -139,6 +133,10 @@ public function create(?string $site = null, ?string $type = null, ?string $lang | |
| $indexSettings | ||
| ); | ||
|
|
||
| if ($runTimestamp) { | ||
| $indexService = new SwappingIndexService($indexService, $runTimestamp); | ||
| } | ||
|
|
||
| $persisters[] = [ | ||
| 'persister' => new EnginePersister($indexService, $this->documentMapperFactory, $language, $concreteStore), | ||
| 'site' => $name, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace CoreShop2VueStorefrontBundle\Bridge; | ||
|
|
||
| use ONGR\ElasticsearchBundle\Service\IndexService; | ||
|
|
||
| class SwappingIndexService extends IndexService | ||
| { | ||
| private $runTimestamp; | ||
| /** | ||
| * @var IndexService | ||
| */ | ||
| private $baseIndexService; | ||
|
|
||
| public function __construct(IndexService $baseIndexService, string $runTimestamp) | ||
| { | ||
| $this->baseIndexService = $baseIndexService; | ||
| $this->runTimestamp = $runTimestamp; | ||
| } | ||
|
|
||
| /** | ||
| * Flushes ES and adds extra steps needed for swapping (assign alias to new index, remove from old indices, drop old indices) | ||
| * | ||
| * @param array $params | ||
| * @return array | ||
| */ | ||
| public function flush(array $params = []): array | ||
| { | ||
| $return = $this->baseIndexService->flush($params); | ||
|
|
||
| $indicesClient = $this->baseIndexService->getClient()->indices(); | ||
| $settings = $this->baseIndexService->indexSettings; | ||
|
|
||
| $oldIndices = null; | ||
| // if alias doesn't exist, the previous index will have a clashing name with alias we're creating so we have to drop it | ||
| if(!$indicesClient->existsAlias(['name' => $settings->getAlias()])) { | ||
| $this->baseIndexService->dropIndex(); | ||
| } | ||
| else { | ||
| //get index names associated with alias | ||
| $oldIndices = implode(',', array_keys($indicesClient->getAlias(['name' => $settings->getAlias()]))); | ||
| //delete alias from old indices | ||
| $indicesClient->deleteAlias([ | ||
| "index" => $oldIndices, | ||
| "name" => $settings->getAlias() | ||
| ]); | ||
| } | ||
| //assign alias to new index | ||
| $indicesClient->putAlias([ | ||
| "index" => $settings->getIndexName(), | ||
| "name" => $settings->getAlias() | ||
| ]); | ||
|
|
||
| if($oldIndices) { | ||
| //drop old indices | ||
| $indicesClient->delete([ | ||
| "index" => $oldIndices | ||
| ]); | ||
| } | ||
|
|
||
| return $return; | ||
| } | ||
|
|
||
| public function getBaseIndexService(): IndexService | ||
| { | ||
| return $this->baseIndexService; | ||
| } | ||
|
|
||
| public function __call($method, $args) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is unfortunate, but I guess it's the only way to do it. Wish |
||
| { | ||
| if (!method_exists($this, $method) && method_exists($this->baseIndexService, $method)) { | ||
| return $this->baseIndexService->$method($args); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,7 @@ protected function configure() | |
| ->addArgument('language', InputArgument::OPTIONAL, 'Language to index') | ||
| ->addArgument('store', InputArgument::OPTIONAL, 'Site store to index') | ||
| ->addOption('updated-since', 's', InputOption::VALUE_OPTIONAL, 'Fetch objects updated in the relative timeframe ("5minute", "2hour", "1day", "yesterday" etc)') | ||
| ->addOption('swap', null, InputOption::VALUE_OPTIONAL, 'Do a full reingest by swapping indices', false) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Booleans use |
||
| ->setName('vsbridge:index-objects') | ||
| ->setDescription('Indexing objects of given type in vuestorefront'); | ||
| } | ||
|
|
@@ -63,6 +64,7 @@ protected function execute(InputInterface $input, OutputInterface $output) | |
| $language = $input->getArgument('language'); | ||
| $store = $input->getArgument('store'); | ||
|
|
||
| $runTimestamp = date('YmdHis'); | ||
| $sinceDatetime = null; | ||
| if (null !== $since = $input->getOption('updated-since')) { | ||
| $sinceDatetime = new \Datetime(); | ||
|
|
@@ -78,7 +80,7 @@ protected function execute(InputInterface $input, OutputInterface $output) | |
| $style->warning(sprintf('Indexing only updated since: %1$s', $sinceDatetime->format('c'))); | ||
| } | ||
|
|
||
| $importers = $this->importerFactory->create($site, $type, $language, $store, $sinceDatetime); | ||
| $importers = $this->importerFactory->create($site, $type, $language, $store, $sinceDatetime, $input->getOption('swap') ? $runTimestamp : null); | ||
|
|
||
| /** @var ImporterInterface $importer */ | ||
| foreach ($importers as $importer) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need this to be configurable, it will never be changed to anything else.