Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/Search/Comb/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Statamic\Search\Comb;

use Closure;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Statamic\Facades\File;
use Statamic\Search\Comb\Exceptions\NoQuery;
Expand All @@ -16,6 +17,8 @@

class Index extends BaseIndex
{
protected ?Collection $pending = null;

public function search($query)
{
return (new Query($this))->query($query);
Expand Down Expand Up @@ -111,6 +114,12 @@ public function delete($document)

public function insertDocuments(Documents $documents)
{
if (! is_null($this->pending)) {
$this->pending = $documents->union($this->pending);

return;
}

$this->locked(function () use ($documents) {
try {
$data = $this->data();
Expand All @@ -122,6 +131,23 @@ public function insertDocuments(Documents $documents)
});
}

public function update()
{
$this->pending = collect();

try {
parent::update();
} finally {
[$pending, $this->pending] = [$this->pending, null];
}

if ($pending->isNotEmpty()) {
$this->locked(fn () => $this->save($pending));
}

return $this;
}

public function deleteIndex()
{
File::delete($this->path());
Expand Down
64 changes: 64 additions & 0 deletions tests/Search/CombIndexTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,28 @@

namespace Tests\Search;

use Facades\Tests\Factories\EntryFactory;
use Illuminate\Contracts\Cache\Lock;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Filesystem\Filesystem as Files;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Cache;
use Mockery;
use PHPUnit\Framework\Attributes\Test;
use Statamic\Contracts\Search\Searchable;
use Statamic\Facades\Collection;
use Statamic\Facades\Search;
use Statamic\Search\Comb\Index;
use Statamic\Search\Documents;
use Tests\PreventSavingStacheItemsToDisk;
use Tests\TestCase;

class CombIndexTest extends TestCase
{
use IndexTests {
tearDown as protected indexTestsTearDown;
}
use PreventSavingStacheItemsToDisk;

private $fs;

Expand Down Expand Up @@ -117,6 +124,63 @@ public function delete_rewrites_the_index_when_the_reference_is_present()
);
}

#[Test]
public function updating_on_a_sync_queue_writes_the_index_file_once()
{
$files = $this->prepareUpdate(250);

Search::index('test')->update();

$files->shouldHaveReceived('put')->once();
$this->assertCount(250, json_decode(file_get_contents($this->tmpDir.'/test.json'), true));
}

#[Test]
public function updating_on_a_faked_bus_deletes_the_index_and_writes_nothing()
{
Bus::fake();
$files = $this->prepareUpdate(3);

Search::index('test')->update();

$files->shouldNotHaveReceived('put');
$this->assertFileDoesNotExist($this->tmpDir.'/test.json');
}

#[Test]
public function inserting_outside_an_update_writes_immediately()
{
$files = $this->prepareUpdate(0);

Search::index('test')->insertDocuments(new Documents(['entry::a' => ['title' => 'Foo']]));
Search::index('test')->insertDocuments(new Documents(['entry::b' => ['title' => 'Bar']]));

$files->shouldHaveReceived('put')->twice();
$this->assertCount(3, json_decode(file_get_contents($this->tmpDir.'/test.json'), true));
}

private function prepareUpdate(int $entries)
{
$this->createIndexFile(['entry::stale' => ['title' => 'Stale']]);

config([
'statamic.search.chunk_size' => 100,
'statamic.search.drivers.local.path' => $this->tmpDir,
'statamic.search.indexes.test' => ['driver' => 'local', 'searchables' => 'collection:blog', 'fields' => ['title']],
]);

Collection::make('blog')->save();

for ($i = 1; $i <= $entries; $i++) {
EntryFactory::collection('blog')->id("entry-$i")->slug("entry-$i")->data(['title' => "Entry $i"])->create();
}

$files = Mockery::mock(Files::class)->makePartial();
$this->instance('files', $files);

return $files;
}

#[Test]
public function inserting_holds_the_index_lock_across_the_read_and_the_write()
{
Expand Down
Loading