From 938f702d3c6b1ec175bbd2efceaf256f41a5781a Mon Sep 17 00:00:00 2001 From: edalzell Date: Wed, 29 Jul 2026 15:39:50 -0400 Subject: [PATCH] Stop re-checking index existence on every Algolia write `settingsInitialized` was only set inside the branch that runs when the index does not exist. Once an index had been created, the flag stayed false forever, so every call to client() re-ran exists() and spent an extra listIndices() API call before each write. On a 2,773 document reindex (chunk size 10, 278 jobs) this meant 280 listIndices() calls costing ~24.5s, roughly half of all the time the reindex spent talking to Algolia. Set the flag regardless of whether the index already existed, so the check happens at most once per index instance. Co-Authored-By: Claude Opus 5 --- src/Search/Algolia/Index.php | 10 ++++++++-- tests/Search/AlgoliaIndexTest.php | 32 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/Search/Algolia/Index.php b/src/Search/Algolia/Index.php index 6eab453935b..c054e117cf6 100644 --- a/src/Search/Algolia/Index.php +++ b/src/Search/Algolia/Index.php @@ -26,8 +26,14 @@ public function __construct(SearchClient $client, $name, $config, $locale) protected function client(): SearchClient { - if (! $this->settingsInitialized && isset($this->config['settings']) && ! $this->exists()) { - $this->client->setSettings($this->name, $this->config['settings']); + if (! $this->settingsInitialized && isset($this->config['settings'])) { + if (! $this->exists()) { + $this->client->setSettings($this->name, $this->config['settings']); + } + + // Mark as initialized either way. Otherwise, when the index already + // exists, we'd never stop checking and every write would spend an + // extra API call on listIndices(). $this->settingsInitialized = true; } diff --git a/tests/Search/AlgoliaIndexTest.php b/tests/Search/AlgoliaIndexTest.php index 06470f3d0e3..510cde1dc70 100644 --- a/tests/Search/AlgoliaIndexTest.php +++ b/tests/Search/AlgoliaIndexTest.php @@ -2,8 +2,11 @@ namespace Tests\Search; +use Algolia\AlgoliaSearch\Api\SearchClient; use Mockery; +use PHPUnit\Framework\Attributes\Test; use Statamic\Search\Algolia\Index as AlgoliaIndex; +use Statamic\Search\Documents; use Tests\TestCase; class AlgoliaIndexTest extends TestCase @@ -21,4 +24,33 @@ public function getIndex($name, $config, $locale) return new AlgoliaIndex($client, $name, $config, $locale); } + + #[Test] + public function it_only_checks_whether_an_existing_index_exists_once() + { + $client = Mockery::mock(SearchClient::class); + $client->shouldReceive('listIndices')->once()->andReturn(['items' => [['name' => 'test']]]); + $client->shouldNotReceive('setSettings'); + $client->shouldReceive('saveObjects')->times(3); + + $index = new AlgoliaIndex($client, 'test', ['settings' => ['hitsPerPage' => 20]], null); + + $index->insertDocuments(new Documents(collect(['one' => ['title' => 'One']]))); + $index->insertDocuments(new Documents(collect(['two' => ['title' => 'Two']]))); + $index->insertDocuments(new Documents(collect(['three' => ['title' => 'Three']]))); + } + + #[Test] + public function it_applies_settings_once_when_the_index_does_not_exist() + { + $client = Mockery::mock(SearchClient::class); + $client->shouldReceive('listIndices')->once()->andReturn(['items' => []]); + $client->shouldReceive('setSettings')->once()->with('test', ['hitsPerPage' => 20]); + $client->shouldReceive('saveObjects')->twice(); + + $index = new AlgoliaIndex($client, 'test', ['settings' => ['hitsPerPage' => 20]], null); + + $index->insertDocuments(new Documents(collect(['one' => ['title' => 'One']]))); + $index->insertDocuments(new Documents(collect(['two' => ['title' => 'Two']]))); + } }