Skip to content

Commit ed2307c

Browse files
committed
MAGE-840 Refactor replica ranking logic
1 parent 1e788fd commit ed2307c

File tree

4 files changed

+98
-111
lines changed

4 files changed

+98
-111
lines changed

Api/Product/ReplicaManagerInterface.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,25 @@
22

33
namespace Algolia\AlgoliaSearch\Api\Product;
44

5+
use Algolia\AlgoliaSearch\Exceptions\AlgoliaException;
6+
use Algolia\AlgoliaSearch\Exceptions\ExceededRetriesException;
7+
use Magento\Framework\Exception\LocalizedException;
8+
use Magento\Framework\Exception\NoSuchEntityException;
9+
510
interface ReplicaManagerInterface
611
{
7-
12+
/**
13+
* Configure replicas in Algolia based on the sorting configuration in Magento
14+
*
15+
* @param string $indexName Could be tmp (legacy impl)
16+
* @param int $storeId
17+
* @param array<string, mixed> $primaryIndexSettings
18+
* @return void
19+
*
20+
* @throws AlgoliaException
21+
* @throws ExceededRetriesException
22+
* @throws LocalizedException
23+
* @throws NoSuchEntityException
24+
*/
25+
public function handleReplicas(string $indexName, int $storeId, array $primaryIndexSettings): void;
826
}

Helper/Entity/ProductHelper.php

Lines changed: 31 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Algolia\AlgoliaSearch\Helper\Entity;
44

5+
use Algolia\AlgoliaSearch\Api\Product\ReplicaManagerInterface;
56
use Algolia\AlgoliaSearch\Exception\ProductDeletedException;
67
use Algolia\AlgoliaSearch\Exception\ProductDisabledException;
78
use Algolia\AlgoliaSearch\Exception\ProductNotVisibleException;
@@ -14,7 +15,6 @@
1415
use Algolia\AlgoliaSearch\Helper\Entity\Product\PriceManager;
1516
use Algolia\AlgoliaSearch\Helper\Image as ImageHelper;
1617
use Algolia\AlgoliaSearch\Helper\Logger;
17-
use Algolia\AlgoliaSearch\Model\Product\ReplicaManager;
1818
use Magento\Bundle\Model\Product\Type as BundleProductType;
1919
use Magento\Catalog\Model\Product;
2020
use Magento\Catalog\Model\Product\Attribute\Source\Status;
@@ -125,7 +125,7 @@ public function __construct(
125125
protected GroupCollection $groupCollection,
126126
protected GroupExcludedWebsiteRepositoryInterface $groupExcludedWebsiteRepository,
127127
protected ImageHelper $imageHelper,
128-
protected ReplicaManager $replicaManager
128+
protected ReplicaManagerInterface $replicaManager
129129
) {}
130130

131131
/**
@@ -376,7 +376,7 @@ public function setSettings(string $indexName, string $indexNameTmp, int $storeI
376376
/*
377377
* Handle replicas
378378
*/
379-
$this->setReplicaSettings($indexName, $storeId);
379+
$this->replicaManager->handleReplicas($indexName, $storeId, $indexSettings);
380380

381381
if ($saveToTmpIndicesToo === true) {
382382
try {
@@ -403,71 +403,6 @@ public function setSettings(string $indexName, string $indexNameTmp, int $storeI
403403
}
404404
}
405405

406-
protected function setReplicaSettings(string $indexName, int $storeId): void
407-
{
408-
$this->replicaManager->handleReplicas($indexName, $storeId);
409-
410-
return;
411-
412-
$sortingIndices = $this->configHelper->getSortingIndices($indexName, $storeId);
413-
$replicas = [];
414-
415-
if ($this->configHelper->isInstantEnabled($storeId)) {
416-
$replicas = array_values(array_map(function ($sortingIndex) {
417-
return $sortingIndex['name'];
418-
}, $sortingIndices));
419-
}
420-
421-
// Managing Virtual Replica
422-
if ($this->configHelper->useVirtualReplica($storeId)) {
423-
$replicas = $this->handleVirtualReplica($replicas);
424-
}
425-
426-
// Merge current replicas with sorting replicas to not delete A/B testing replica indices
427-
try {
428-
$currentSettings = $this->algoliaHelper->getSettings($indexName);
429-
if (is_array($currentSettings) && array_key_exists('replicas', $currentSettings)) {
430-
$replicas = array_values(array_unique(array_merge($replicas, $currentSettings['replicas'])));
431-
}
432-
} catch (AlgoliaException $e) {
433-
if ($e->getCode() !== 404) {
434-
throw $e;
435-
}
436-
}
437-
438-
if (count($replicas) > 0) {
439-
$this->algoliaHelper->setSettings($indexName, ['replicas' => $replicas]);
440-
$this->logger->log('Setting replicas to "' . $indexName . '" index.');
441-
$this->logger->log('Replicas: ' . json_encode($replicas));
442-
$setReplicasTaskId = $this->algoliaHelper->getLastTaskId();
443-
if (!$this->configHelper->useVirtualReplica($storeId)) {
444-
foreach ($sortingIndices as $values) {
445-
$replicaName = $values['name'];
446-
$indexSettings['ranking'] = $values['ranking'];
447-
$this->algoliaHelper->setSettings($replicaName, $indexSettings, false, true);
448-
$this->logger->log('Setting settings to "' . $replicaName . '" replica.');
449-
$this->logger->log('Settings: ' . json_encode($indexSettings));
450-
}
451-
} else {
452-
foreach ($sortingIndices as $values) {
453-
$replicaName = $values['name'];
454-
array_unshift($customRanking, $values['ranking'][0]);
455-
$replicaSetting['customRanking'] = $customRanking;
456-
$this->algoliaHelper->setSettings($replicaName, $replicaSetting, false, false);
457-
$this->logger->log('Setting settings to "' . $replicaName . '" replica.');
458-
$this->logger->log('Settings: ' . json_encode($replicaSetting));
459-
}
460-
}
461-
} else {
462-
$this->algoliaHelper->setSettings($indexName, ['replicas' => []]);
463-
$this->logger->log('Removing replicas from "' . $indexName . '" index');
464-
$setReplicasTaskId = $this->algoliaHelper->getLastTaskId();
465-
}
466-
467-
// Commented out as it doesn't delete anything now because of merging replica indices earlier
468-
// $this->deleteUnusedReplicas($indexName, $replicas, $setReplicasTaskId);
469-
}
470-
471406
/**
472407
* @param $categoryIds
473408
* @param $storeId
@@ -1484,7 +1419,7 @@ public function handleVirtualReplica($replicas)
14841419
* Return a formatted Algolia `replicas` configuration for the provided sorting indices
14851420
* @param mixed[] $sortingIndices Array of sorting index objects
14861421
* @return string[]
1487-
* @deprecated This method is moving to ReplicaManager where it is being re-envisioned
1422+
* @deprecated This method should no longer used
14881423
*/
14891424
protected function decorateReplicasSetting(array $sortingIndices): array {
14901425
return array_map(
@@ -1508,34 +1443,35 @@ function($sort) {
15081443
* @throws ExceededRetriesException
15091444
* @throws LocalizedException
15101445
* @throws NoSuchEntityException
1511-
* @deprecated This function may be removed in a future release
1446+
* @deprecated This function will be removed in a future release
1447+
* @see Algolia::AlgoliaSearch::Api::Product::ReplicaManagerInterface
15121448
*/
15131449
public function handlingReplica(string $indexName, int $storeId, $sortingAttribute = false): void
15141450
{
1515-
// $sortingIndices = $this->configHelper->getSortingIndices($indexName, $storeId, null, $sortingAttribute);
1516-
// if ($this->configHelper->isInstantEnabled($storeId)) {
1517-
// $newReplicas = $this->decorateReplicasSetting($sortingIndices);
1518-
//
1519-
// try {
1520-
// $currentSettings = $this->algoliaHelper->getSettings($indexName);
1521-
// if (array_key_exists('replicas', $currentSettings)) {
1522-
// $oldReplicas = $currentSettings['replicas'];
1523-
// $replicasToDelete = array_diff($oldReplicas, $newReplicas);
1524-
// $this->algoliaHelper->setSettings($indexName, ['replicas' => $newReplicas]);
1525-
// $setReplicasTaskId = $this->algoliaHelper->getLastTaskId();
1526-
// $this->algoliaHelper->waitLastTask($indexName, $setReplicasTaskId);
1527-
// if (count($replicasToDelete) > 0) {
1528-
// foreach ($replicasToDelete as $deletedReplica) {
1529-
// $this->algoliaHelper->deleteIndex($deletedReplica);
1530-
// }
1531-
// }
1532-
// }
1533-
// } catch (AlgoliaException $e) {
1534-
// if ($e->getCode() !== 404) {
1535-
// $this->logger->log($e->getMessage());
1536-
// throw $e;
1537-
// }
1538-
// }
1539-
// }
1451+
$sortingIndices = $this->configHelper->getSortingIndices($indexName, $storeId, null, $sortingAttribute);
1452+
if ($this->configHelper->isInstantEnabled($storeId)) {
1453+
$newReplicas = $this->decorateReplicasSetting($sortingIndices);
1454+
1455+
try {
1456+
$currentSettings = $this->algoliaHelper->getSettings($indexName);
1457+
if (array_key_exists('replicas', $currentSettings)) {
1458+
$oldReplicas = $currentSettings['replicas'];
1459+
$replicasToDelete = array_diff($oldReplicas, $newReplicas);
1460+
$this->algoliaHelper->setSettings($indexName, ['replicas' => $newReplicas]);
1461+
$setReplicasTaskId = $this->algoliaHelper->getLastTaskId();
1462+
$this->algoliaHelper->waitLastTask($indexName, $setReplicasTaskId);
1463+
if (count($replicasToDelete) > 0) {
1464+
foreach ($replicasToDelete as $deletedReplica) {
1465+
$this->algoliaHelper->deleteIndex($deletedReplica);
1466+
}
1467+
}
1468+
}
1469+
} catch (AlgoliaException $e) {
1470+
if ($e->getCode() !== 404) {
1471+
$this->logger->log($e->getMessage());
1472+
throw $e;
1473+
}
1474+
}
1475+
}
15401476
}
15411477
}

Model/Product/ReplicaManager.php

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace Algolia\AlgoliaSearch\Model\Product;
46

57
use Algolia\AlgoliaSearch\Api\Product\ReplicaManagerInterface;
@@ -187,23 +189,17 @@ protected function getPossibleMagentoReplicaSettings(string $indexName, int $sto
187189
}
188190

189191
/**
190-
* @param string $indexName - could be tmp (legacy impl)
191-
* @param int $storeId
192-
* @return void
193-
*
194-
* @throws AlgoliaException
195-
* @throws ExceededRetriesException
196-
* @throws LocalizedException
197-
* @throws NoSuchEntityException
192+
* @inheritDoc
198193
*/
199-
public function handleReplicas(string $indexName, int $storeId): void
194+
public function handleReplicas(string $indexName, int $storeId, array $primaryIndexSettings): void
200195
{
196+
// TODO: Determine if InstantSearch is a hard requirement (i.e. headless implementations may still need replicas)
201197
if ($this->configHelper->isInstantEnabled($storeId)
202198
&& $this->hasReplicaConfigurationChanged($indexName, $storeId))
203199
{
204-
// We only care about configuring ranking for replicas that were added!
200+
// TODO: Handle ranking adjustments when toggling virtual vs standard replicas
205201
$addedReplicas = $this->setReplicasOnPrimaryIndex($indexName, $storeId);
206-
$this->configureRanking($addedReplicas);
202+
$this->configureRanking($indexName, $storeId, $addedReplicas, $primaryIndexSettings);
207203
}
208204
}
209205

@@ -250,11 +246,46 @@ protected function deleteReplicas(array $replicasToDelete): void
250246
}
251247
}
252248

253-
/** Apply ranking settings to the replica indices */
254-
protected function configureRanking(array $replicas): void
249+
/**
250+
* Apply ranking settings to the added replica indices
251+
* @param string $indexName
252+
* @param int $storeId
253+
* @param string[] $replicas
254+
* @param array<string, mixed> $primaryIndexSettings
255+
* @return void
256+
* @throws AlgoliaException
257+
* @throws LocalizedException
258+
* @throws NoSuchEntityException
259+
*/
260+
protected function configureRanking(string $indexName, int $storeId, array $replicas, array $primaryIndexSettings): void
255261
{
256-
foreach ($replicas as $replica) {
257-
262+
$sortingIndices = $this->configHelper->getSortingIndices($indexName, $storeId);
263+
$replicaDetails = array_filter(
264+
$sortingIndices,
265+
function($replica) use ($replicas) {
266+
return in_array($replica['name'], $replicas);
267+
}
268+
);
269+
foreach ($replicaDetails as $replica) {
270+
$replicaName = $replica['name'];
271+
// Virtual replicas - relevant sort
272+
if ($replica['virtualReplica']) {
273+
$customRanking = array_key_exists('customRanking', $primaryIndexSettings)
274+
? $primaryIndexSettings['customRanking']
275+
: [];
276+
array_unshift($customRanking, $replica['ranking'][0]);
277+
$this->algoliaHelper->setSettings(
278+
$replicaName,
279+
[ 'customRanking' => $customRanking ]
280+
);
281+
// Standard replicas - exhaustive sort
282+
} else {
283+
$primaryIndexSettings['ranking'] = $replica['ranking'];
284+
$this->algoliaHelper->setSettings(
285+
$replicaName,
286+
$primaryIndexSettings
287+
);
288+
}
258289
}
259290
}
260291
}

etc/di.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535

3636
<preference for="Algolia\AlgoliaSearch\Api\Insights\EventsInterface" type="Algolia\AlgoliaSearch\Model\Insights\Events"/>
3737

38+
<preference for="Algolia\AlgoliaSearch\Api\Product\ReplicaManagerInterface" type="Algolia\AlgoliaSearch\Model\Product\ReplicaManager"/>
39+
3840
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
3941
<arguments>
4042
<argument name="collections" xsi:type="array">

0 commit comments

Comments
 (0)