Skip to content

Commit

Permalink
[5.x] Fixed an issue where stache indexing can cause an infinite loop…
Browse files Browse the repository at this point in the history
… for workers (#11185)

Co-authored-by: Simon Geoghegan <[email protected]>
Co-authored-by: Jason Varga <[email protected]>
  • Loading branch information
3 people authored Dec 5, 2024
1 parent a345e00 commit 9962a63
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 3 deletions.
9 changes: 6 additions & 3 deletions src/Stache/Indexes/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,18 @@ public function load()
return $this;
}

static::$currentlyLoading = $this->store->key().'/'.$this->name;
$loadingKey = $this->store->key().'/'.$this->name;
$currentlyLoadingThis = static::$currentlyLoading === $loadingKey;

static::$currentlyLoading = $loadingKey;

$this->loaded = true;

if (Statamic::isWorker()) {
if (Statamic::isWorker() && ! $currentlyLoadingThis) {
$this->loaded = false;
}

debugbar()->addMessage("Loading index: {$this->store->key()}/{$this->name}", 'stache');
debugbar()->addMessage("Loading index: {$loadingKey}", 'stache');

$this->items = Stache::cacheStore()->get($this->cacheKey());

Expand Down
40 changes: 40 additions & 0 deletions tests/Stache/WorkerInfiniteLoopTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Tests\Stache;

use Facades\Tests\Factories\EntryFactory;
use Illuminate\Support\Facades\Request;
use PHPUnit\Framework\Attributes\Test;
use Statamic\Entries\Collection;
use Statamic\Statamic;
use Tests\PreventSavingStacheItemsToDisk;
use Tests\TestCase;

class WorkerInfiniteLoopTest extends TestCase
{
use PreventSavingStacheItemsToDisk;

#[Test]
public function infinite_loops_are_prevented_when_running_workers()
{
// NOTE: We are not using the `config(['cache.default' => 'file'])` override as that
// will cause an infinite loop on failure instead of a segfault.

// `Statamic::isWorker()` should return false by default.
$this->assertFalse(Statamic::isWorker());

// Swap the request with one that will cause `Statamic::isWorker()` to return `true`.
// NOTE: Cannot use `Tests\Fakes\FakeArtisanRequest` as that does not have the cookies
// object initialised and `auth()->user()` will throw an Exception.
Request::swap(request()->duplicate(server: [
'argv' => ['artisan', 'queue:work'],
'argc' => 2,
]));

// `Statamic::isWorker()` should return true when being called from any command beginning with `queue:`.
$this->assertTrue(Statamic::isWorker());

Collection::make('test')->save();
EntryFactory::id('alfa-id')->collection('test')->slug('alfa')->data(['title' => 'Alfa'])->create();
}
}

0 comments on commit 9962a63

Please sign in to comment.