|
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 |
|
@@ -260,7 +261,7 @@ protected function setReplicasOnPrimaryIndex(int $storeId): array
|
260 | 261 | $setReplicasTaskId = $this->algoliaHelper->getLastTaskId();
|
261 | 262 | $this->algoliaHelper->waitLastTask($indexName, $setReplicasTaskId);
|
262 | 263 | $this->clearAlgoliaReplicaSettingCache($indexName);
|
263 |
| - $this->deleteIndices($replicasToDelete); |
| 264 | + $this->deleteReplicas($replicasToDelete); |
264 | 265 |
|
265 | 266 | if (self::_DEBUG) {
|
266 | 267 | $this->logger->log(
|
@@ -354,21 +355,74 @@ protected function getBareIndexNameFromReplicaSetting(string $replicaSetting): s
|
354 | 355 | }
|
355 | 356 |
|
356 | 357 | /**
|
357 |
| - * @param array $replicasToDelete |
358 |
| - * @param bool $waitLastTask |
| 358 | + * Delete replica indices |
| 359 | + * |
| 360 | + * @param array $replicasToDelete - which replicas to delete |
| 361 | + * @param bool $waitLastTask - wait until deleting next replica (default: false) |
| 362 | + * @param bool $prevalidate - verify replica is not attached to a primary index before attempting to delete (default: false) |
359 | 363 | * @return void
|
360 | 364 | * @throws AlgoliaException
|
| 365 | + * @throws ExceededRetriesException |
361 | 366 | */
|
362 |
| - protected function deleteIndices(array $replicasToDelete, bool $waitLastTask = false): void |
| 367 | + protected function deleteReplicas(array $replicasToDelete, bool $waitLastTask = false, bool $prevalidate = false): void |
363 | 368 | {
|
364 | 369 | foreach ($replicasToDelete as $deletedReplica) {
|
365 |
| - $this->algoliaHelper->deleteIndex($deletedReplica); |
| 370 | + $this->deleteReplica($deletedReplica, $prevalidate); |
366 | 371 | if ($waitLastTask) {
|
367 | 372 | $this->algoliaHelper->waitLastTask($deletedReplica);
|
368 | 373 | }
|
369 | 374 | }
|
370 | 375 | }
|
371 | 376 |
|
| 377 | + /** |
| 378 | + * @throws AlgoliaException |
| 379 | + * @throws ExceededRetriesException |
| 380 | + */ |
| 381 | + protected function deleteReplica(string $replicaIndexName, bool $precheck = false): void |
| 382 | + { |
| 383 | + if ($precheck) { |
| 384 | + $settings = $this->algoliaHelper->getSettings($replicaIndexName); |
| 385 | + if (isset($settings[self::ALGOLIA_SETTINGS_KEY_PRIMARY])) { |
| 386 | + $this->detachReplica($settings[self::ALGOLIA_SETTINGS_KEY_PRIMARY], $replicaIndexName); |
| 387 | + } |
| 388 | + } |
| 389 | + |
| 390 | + $this->algoliaHelper->deleteIndex($replicaIndexName); |
| 391 | + } |
| 392 | + |
| 393 | + /** |
| 394 | + * Detach a single replica from its primary index |
| 395 | + * |
| 396 | + * @throws ExceededRetriesException |
| 397 | + * @throws AlgoliaException |
| 398 | + */ |
| 399 | + protected function detachReplica(string $primaryIndexName, string $replicaIndexName): void |
| 400 | + { |
| 401 | + $settings = $this->algoliaHelper->getSettings($primaryIndexName); |
| 402 | + if (!isset($settings[self::ALGOLIA_SETTINGS_KEY_REPLICAS])) { |
| 403 | + return; |
| 404 | + } |
| 405 | + $newReplicas = $this->removeReplicaFromReplicaSetting($settings[self::ALGOLIA_SETTINGS_KEY_REPLICAS], $replicaIndexName); |
| 406 | + $this->algoliaHelper->setSettings($primaryIndexName, [ self::ALGOLIA_SETTINGS_KEY_REPLICAS => $newReplicas]); |
| 407 | + $this->algoliaHelper->waitLastTask($primaryIndexName); |
| 408 | + } |
| 409 | + |
| 410 | + /** |
| 411 | + * Remove a single replica from the replica setting array |
| 412 | + * (Can feature virtual or standard) |
| 413 | + */ |
| 414 | + protected function removeReplicaFromReplicaSetting(array $replicaSetting, string $replicaToRemove): array |
| 415 | + { |
| 416 | + return array_filter( |
| 417 | + $replicaSetting, |
| 418 | + function ($replicaIndexSetting) use ($replicaToRemove) { |
| 419 | + $escaped = preg_quote($replicaToRemove); |
| 420 | + $regex = '/^' . $escaped . '|virtual\(' . $escaped . '\)$/'; |
| 421 | + return !preg_match($regex, $replicaToRemove); |
| 422 | + } |
| 423 | + ); |
| 424 | + } |
| 425 | + |
372 | 426 | /**
|
373 | 427 | * Apply ranking settings to the added replica indices
|
374 | 428 | * @param int $storeId
|
@@ -416,7 +470,7 @@ function($replica) use ($replicas) {
|
416 | 470 | */
|
417 | 471 | public function isReplicaSyncEnabled(int $storeId): bool
|
418 | 472 | {
|
419 |
| - return $this->configHelper->isInstantEnabled($storeId); |
| 473 | + return $this->configHelper->isInstantEnabled($storeId) && $this->configHelper->isEnabledBackend($storeId); |
420 | 474 | }
|
421 | 475 |
|
422 | 476 | /**
|
@@ -449,7 +503,7 @@ public function deleteReplicasFromAlgolia(int $storeId, bool $unused = false): v
|
449 | 503 | $this->clearReplicasSettingInAlgolia($primaryIndexName);
|
450 | 504 | }
|
451 | 505 |
|
452 |
| - $this->deleteIndices($replicasToDelete); |
| 506 | + $this->deleteReplicas($replicasToDelete, true, true); |
453 | 507 |
|
454 | 508 | if ($unused) {
|
455 | 509 | $this->clearUnusedReplicaIndicesCache($storeId);
|
|
0 commit comments