|
18 | 18 | use Algolia\AlgoliaSearch\Validator\VirtualReplicaValidatorFactory;
|
19 | 19 | use Magento\Framework\Exception\LocalizedException;
|
20 | 20 | use Magento\Framework\Exception\NoSuchEntityException;
|
| 21 | +use Magento\Store\Model\StoreManagerInterface; |
21 | 22 |
|
22 | 23 | /**
|
23 | 24 | * This class is responsible for managing the business logic related to translating the
|
@@ -53,6 +54,7 @@ public function __construct(
|
53 | 54 | protected IndexNameFetcher $indexNameFetcher,
|
54 | 55 | protected StoreNameFetcher $storeNameFetcher,
|
55 | 56 | protected SortingTransformer $sortingTransformer,
|
| 57 | + protected StoreManagerInterface $storeManager, |
56 | 58 | protected Logger $logger
|
57 | 59 | )
|
58 | 60 | {}
|
@@ -160,7 +162,7 @@ function ($algoliaReplicaSetting) use ($baseIndexName) {
|
160 | 162 | protected function isMagentoReplicaIndex(string $replicaIndexName, int|string $storeIdOrIndex): bool
|
161 | 163 | {
|
162 | 164 | $primaryIndexName = is_string($storeIdOrIndex) ? $storeIdOrIndex : $this->indexNameFetcher->getProductIndexName($storeIdOrIndex);
|
163 |
| - return str_starts_with($replicaIndexName, $primaryIndexName); |
| 165 | + return $replicaIndexName !== $primaryIndexName && str_starts_with($replicaIndexName, $primaryIndexName); |
164 | 166 | }
|
165 | 167 |
|
166 | 168 | /**
|
@@ -404,77 +406,85 @@ public function getMaxVirtualReplicasPerIndex() : int
|
404 | 406 | }
|
405 | 407 |
|
406 | 408 | /**
|
407 |
| - * @param string $indexName |
408 |
| - * @param array $replicas |
409 |
| - * @param int $setReplicasTaskId |
410 |
| - * @return void |
411 | 409 | * @throws AlgoliaException
|
412 |
| - * @throws ExceededRetriesException |
413 | 410 | */
|
414 |
| - protected function deleteUnusedReplicas(string $indexName, array $replicas, int $setReplicasTaskId): void |
| 411 | + protected function clearReplicasSettingInAlgolia(string $primaryIndexName): void |
415 | 412 | {
|
416 |
| - $indicesToDelete = []; |
| 413 | + $this->algoliaHelper->setSettings($primaryIndexName, [ self::ALGOLIA_SETTINGS_KEY_REPLICAS => []]); |
| 414 | + $this->algoliaHelper->waitLastTask($primaryIndexName); |
| 415 | + } |
417 | 416 |
|
418 |
| - $allIndices = $this->algoliaHelper->listIndexes(); |
419 |
| - foreach ($allIndices['items'] as $indexInfo) { |
420 |
| - //skip any indices that don't match the primary index |
421 |
| - if (mb_strpos($indexInfo['name'], $indexName) !== 0 || $indexInfo['name'] === $indexName) { |
422 |
| - continue; |
423 |
| - } |
| 417 | + /** |
| 418 | + * @throws AlgoliaException |
| 419 | + * @throws NoSuchEntityException |
| 420 | + * @throws LocalizedException |
| 421 | + */ |
| 422 | + public function deleteReplicasFromAlgolia(int $storeId, bool $unused = false): void |
| 423 | + { |
| 424 | + $primaryIndexName = $this->indexNameFetcher->getProductIndexName($storeId); |
424 | 425 |
|
425 |
| - // skip temp indices and expected replicas |
426 |
| - if (mb_strpos($indexInfo['name'], IndexNameFetcher::INDEX_TEMP_SUFFIX) === false && in_array($indexInfo['name'], $replicas) === false) { |
427 |
| - $indicesToDelete[] = $indexInfo['name']; |
428 |
| - } |
| 426 | + if ($unused) { |
| 427 | + $replicasToDelete = $this->getUnusedReplicaIndices($primaryIndexName); |
| 428 | + } else { |
| 429 | + $replicasToDelete = $this->getMagentoReplicaIndicesFromAlgolia($primaryIndexName); |
| 430 | + $this->clearReplicasSettingInAlgolia($primaryIndexName); |
429 | 431 | }
|
430 | 432 |
|
431 |
| - if (count($indicesToDelete) > 0) { |
432 |
| - $this->algoliaHelper->waitLastTask($indexName, $setReplicasTaskId); |
433 |
| - |
434 |
| - foreach ($indicesToDelete as $indexToDelete) { |
435 |
| - $this->algoliaHelper->deleteIndex($indexToDelete); |
436 |
| - } |
437 |
| - } |
| 433 | + $this->deleteReplicaIndices($replicasToDelete); |
438 | 434 | }
|
439 | 435 |
|
440 | 436 | /**
|
441 |
| - * @throws AlgoliaException |
| 437 | + * @throws LocalizedException |
442 | 438 | */
|
443 |
| - protected function clearReplicasSettingInAlgolia(string $primaryIndexName): void |
| 439 | + protected function getMagentoReplicaIndicesFromAlgolia(string $primaryIndexName): array |
444 | 440 | {
|
445 |
| - $this->algoliaHelper->setSettings($primaryIndexName, [ self::ALGOLIA_SETTINGS_KEY_REPLICAS => []]); |
| 441 | + return $this->getBareIndexNamesFromReplicaSetting($this->getMagentoReplicaConfigurationFromAlgolia($primaryIndexName)); |
446 | 442 | }
|
447 | 443 |
|
448 | 444 | /**
|
449 |
| - * @throws AlgoliaException |
| 445 | + * @return string[] |
450 | 446 | * @throws NoSuchEntityException
|
451 | 447 | * @throws LocalizedException
|
| 448 | + * @throws AlgoliaException |
452 | 449 | */
|
453 |
| - public function deleteReplicasFromAlgolia(int $storeId, bool $unusedOnly = false): void |
| 450 | + protected function getUnusedReplicaIndices(string $primaryIndexName): array |
454 | 451 | {
|
455 |
| - $primaryIndexName = $this->indexNameFetcher->getProductIndexName($storeId); |
456 |
| - |
457 |
| - // get all possible Magento managed product indices for this store |
| 452 | + $currentReplicas = $this->getMagentoReplicaIndicesFromAlgolia($primaryIndexName); |
| 453 | + $unusedReplicas = []; |
458 | 454 | $allIndices = $this->algoliaHelper->listIndexes();
|
459 | 455 |
|
460 |
| - $currentReplicas = $this->getBareIndexNamesFromReplicaSetting($this->getMagentoReplicaConfigurationFromAlgolia($primaryIndexName)); |
461 |
| - |
462 |
| - if (!$unusedOnly) { |
463 |
| - $this->clearReplicasSettingInAlgolia($primaryIndexName); |
464 |
| - } |
465 |
| - |
466 |
| - $replicasToDelete = []; |
467 |
| - |
468 | 456 | foreach ($allIndices['items'] as $indexInfo) {
|
469 | 457 | $indexName = $indexInfo['name'];
|
470 | 458 | if ($this->isMagentoReplicaIndex($indexName, $primaryIndexName)
|
471 | 459 | && !$this->indexNameFetcher->isTempIndex($indexName)
|
472 |
| - && (!$unusedOnly || !array_search($indexName, $currentReplicas)) |
473 |
| - ) { |
474 |
| - $replicasToDelete[] = $indexName; |
| 460 | + && !$this->indexNameFetcher->isQuerySuggestionsIndex($indexName) |
| 461 | + && !in_array($indexName, $currentReplicas)) |
| 462 | + { |
| 463 | + $unusedReplicas[] = $indexName; |
475 | 464 | }
|
476 | 465 | }
|
477 | 466 |
|
478 |
| - $this->deleteReplicaIndices($replicasToDelete); |
| 467 | + return $unusedReplicas; |
| 468 | + } |
| 469 | + |
| 470 | + /** |
| 471 | + * Get a list of all replica indices for all Magento managed stores |
| 472 | + * (This may be useful in case of cross store replica misconfiguration) |
| 473 | + * @return string[] |
| 474 | + * @throws NoSuchEntityException |
| 475 | + * @throws LocalizedException |
| 476 | + */ |
| 477 | + protected function getAllReplicaIndices(): array |
| 478 | + { |
| 479 | + $replicaIndices = []; |
| 480 | + $storeIds = array_keys($this->storeManager->getStores()); |
| 481 | + foreach ($storeIds as $storeId) { |
| 482 | + $primaryIndexName = $this->indexNameFetcher->getProductIndexName($storeId); |
| 483 | + $replicaIndices = array_merge( |
| 484 | + $replicaIndices, |
| 485 | + $this->getMagentoReplicaIndicesFromAlgolia($primaryIndexName) |
| 486 | + ); |
| 487 | + } |
| 488 | + return array_unique($replicaIndices); |
479 | 489 | }
|
480 | 490 | }
|
0 commit comments