|
41 | 41 | class ReplicaManager implements ReplicaManagerInterface
|
42 | 42 | {
|
43 | 43 | public const ALGOLIA_SETTINGS_KEY_REPLICAS = 'replicas';
|
| 44 | + public const ALGOLIA_SETTINGS_KEY_PRIMARY = 'primary'; |
44 | 45 |
|
45 | 46 | protected const _DEBUG = true;
|
46 | 47 |
|
@@ -272,7 +273,7 @@ protected function setReplicasOnPrimaryIndex(int $storeId): array
|
272 | 273 | $setReplicasTaskId = $this->algoliaHelper->getLastTaskId($storeId);
|
273 | 274 | $this->algoliaHelper->waitLastTask($storeId, $indexName, $setReplicasTaskId);
|
274 | 275 | $this->clearAlgoliaReplicaSettingCache($indexName);
|
275 |
| - $this->deleteIndices($replicasToDelete, false, $storeId); |
| 276 | + $this->deleteReplicas($replicasToDelete, false, false, $storeId); |
276 | 277 |
|
277 | 278 | if (self::_DEBUG) {
|
278 | 279 | $this->logger->log(
|
@@ -366,23 +367,85 @@ protected function getBareIndexNameFromReplicaSetting(string $replicaSetting): s
|
366 | 367 | }
|
367 | 368 |
|
368 | 369 | /**
|
369 |
| - * @param array $replicasToDelete |
370 |
| - * @param bool $waitLastTask |
371 |
| - * @param null $storeId |
| 370 | + * Delete replica indices |
| 371 | + * |
| 372 | + * @param array $replicasToDelete - which replicas to delete |
| 373 | + * @param bool $waitLastTask - wait until deleting next replica (default: false) |
| 374 | + * @param bool $prevalidate - verify replica is not attached to a primary index before attempting to delete (default: false) |
372 | 375 | * @return void
|
373 | 376 | * @throws AlgoliaException
|
374 | 377 | * @throws ExceededRetriesException
|
375 | 378 | */
|
376 |
| - protected function deleteIndices(array $replicasToDelete, bool $waitLastTask = false, $storeId = null): void |
| 379 | + protected function deleteReplicas( |
| 380 | + array $replicasToDelete, |
| 381 | + bool $waitLastTask = false, |
| 382 | + bool $prevalidate = false, |
| 383 | + ?int $storeId = null): void |
377 | 384 | {
|
378 | 385 | foreach ($replicasToDelete as $deletedReplica) {
|
379 |
| - $this->algoliaHelper->deleteIndex($deletedReplica, $storeId); |
| 386 | + $this->deleteReplica($deletedReplica, $prevalidate); |
380 | 387 | if ($waitLastTask) {
|
381 | 388 | $this->algoliaHelper->waitLastTask($storeId, $deletedReplica);
|
382 | 389 | }
|
383 | 390 | }
|
384 | 391 | }
|
385 | 392 |
|
| 393 | + /** |
| 394 | + * @throws AlgoliaException |
| 395 | + * @throws ExceededRetriesException |
| 396 | + */ |
| 397 | + protected function deleteReplica(string $replicaIndexName, bool $precheck = false, ?int $storeId = null): void |
| 398 | + { |
| 399 | + if ($precheck) { |
| 400 | + $settings = $this->algoliaHelper->getSettings($replicaIndexName); |
| 401 | + if (isset($settings[self::ALGOLIA_SETTINGS_KEY_PRIMARY])) { |
| 402 | + $this->detachReplica($settings[self::ALGOLIA_SETTINGS_KEY_PRIMARY], $replicaIndexName, $storeId); |
| 403 | + } |
| 404 | + } |
| 405 | + |
| 406 | + $this->algoliaHelper->deleteIndex($replicaIndexName, $storeId); |
| 407 | + } |
| 408 | + |
| 409 | + /** |
| 410 | + * Detach a single replica from its primary index |
| 411 | + * |
| 412 | + * @throws ExceededRetriesException |
| 413 | + * @throws AlgoliaException |
| 414 | + */ |
| 415 | + protected function detachReplica(string $primaryIndexName, string $replicaIndexName, ?int $storeId = null): void |
| 416 | + { |
| 417 | + $settings = $this->algoliaHelper->getSettings($primaryIndexName); |
| 418 | + if (!isset($settings[self::ALGOLIA_SETTINGS_KEY_REPLICAS])) { |
| 419 | + return; |
| 420 | + } |
| 421 | + $newReplicas = $this->removeReplicaFromReplicaSetting($settings[self::ALGOLIA_SETTINGS_KEY_REPLICAS], $replicaIndexName); |
| 422 | + $this->algoliaHelper->setSettings( |
| 423 | + $primaryIndexName, |
| 424 | + [ self::ALGOLIA_SETTINGS_KEY_REPLICAS => $newReplicas], |
| 425 | + false, |
| 426 | + false, |
| 427 | + '', |
| 428 | + $storeId |
| 429 | + ); |
| 430 | + $this->algoliaHelper->waitLastTask($storeId, $primaryIndexName); |
| 431 | + } |
| 432 | + |
| 433 | + /** |
| 434 | + * Remove a single replica from the replica setting array |
| 435 | + * (Can feature virtual or standard) |
| 436 | + */ |
| 437 | + protected function removeReplicaFromReplicaSetting(array $replicaSetting, string $replicaToRemove): array |
| 438 | + { |
| 439 | + return array_filter( |
| 440 | + $replicaSetting, |
| 441 | + function ($replicaIndexSetting) use ($replicaToRemove) { |
| 442 | + $escaped = preg_quote($replicaToRemove); |
| 443 | + $regex = '/^' . $escaped . '|virtual\(' . $escaped . '\)$/'; |
| 444 | + return !preg_match($regex, $replicaToRemove); |
| 445 | + } |
| 446 | + ); |
| 447 | + } |
| 448 | + |
386 | 449 | /**
|
387 | 450 | * Apply ranking settings to the added replica indices
|
388 | 451 | * @param int $storeId
|
@@ -438,7 +501,7 @@ function($replica) use ($replicas) {
|
438 | 501 | */
|
439 | 502 | public function isReplicaSyncEnabled(int $storeId): bool
|
440 | 503 | {
|
441 |
| - return $this->configHelper->isInstantEnabled($storeId); |
| 504 | + return $this->configHelper->isInstantEnabled($storeId) && $this->configHelper->isEnabledBackend($storeId); |
442 | 505 | }
|
443 | 506 |
|
444 | 507 | /**
|
@@ -479,7 +542,7 @@ public function deleteReplicasFromAlgolia(int $storeId, bool $unused = false): v
|
479 | 542 | $this->clearReplicasSettingInAlgolia($primaryIndexName, $storeId);
|
480 | 543 | }
|
481 | 544 |
|
482 |
| - $this->deleteIndices($replicasToDelete); |
| 545 | + $this->deleteReplicas($replicasToDelete, true, true, $storeId); |
483 | 546 |
|
484 | 547 | if ($unused) {
|
485 | 548 | $this->clearUnusedReplicaIndicesCache($storeId);
|
|
0 commit comments